Commit 85b24ea06b0579dd13551fbf92a0fe243adb9792
Merge branch 'master_dev_msa0311' into 'master_dev'
refactor: GBT28181结构调整 See merge request yunteng/thingskit!368
Showing
57 changed files
with
3812 additions
and
2937 deletions
@@ -36,7 +36,6 @@ public class TkVideoControlController extends BaseController { | @@ -36,7 +36,6 @@ public class TkVideoControlController extends BaseController { | ||
36 | 36 | ||
37 | @GetMapping("/start/{deviceId}/{channelId}") | 37 | @GetMapping("/start/{deviceId}/{channelId}") |
38 | @ApiOperation(value = "视频点播/预览") | 38 | @ApiOperation(value = "视频点播/预览") |
39 | -// @PreAuthorize("@check.checkPermissions({'SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:video:control:play'})") | ||
40 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER')") | 39 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER')") |
41 | public DeferredResult<ResponseResult<StreamContentDTO>> startPlay( | 40 | public DeferredResult<ResponseResult<StreamContentDTO>> startPlay( |
42 | @PathVariable("deviceId") String tbDeviceId, @PathVariable("channelId") String channelId) | 41 | @PathVariable("deviceId") String tbDeviceId, @PathVariable("channelId") String channelId) |
@@ -3,16 +3,17 @@ package org.thingsboard.server.controller.yunteng.media; | @@ -3,16 +3,17 @@ package org.thingsboard.server.controller.yunteng.media; | ||
3 | import com.fasterxml.jackson.databind.JsonNode; | 3 | import com.fasterxml.jackson.databind.JsonNode; |
4 | import io.swagger.annotations.Api; | 4 | import io.swagger.annotations.Api; |
5 | import io.swagger.annotations.ApiOperation; | 5 | import io.swagger.annotations.ApiOperation; |
6 | +import javax.servlet.http.HttpServletRequest; | ||
6 | import lombok.RequiredArgsConstructor; | 7 | import lombok.RequiredArgsConstructor; |
7 | import lombok.extern.slf4j.Slf4j; | 8 | import lombok.extern.slf4j.Slf4j; |
9 | +import org.json.JSONObject; | ||
8 | import org.springframework.web.bind.annotation.*; | 10 | import org.springframework.web.bind.annotation.*; |
11 | +import org.springframework.web.context.request.async.DeferredResult; | ||
9 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 12 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
10 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 13 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
11 | -import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | ||
12 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; | 14 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; |
13 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; | 15 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; |
14 | import org.thingsboard.server.controller.BaseController; | 16 | import org.thingsboard.server.controller.BaseController; |
15 | -import org.thingsboard.server.dao.yunteng.service.TkDeviceService; | ||
16 | import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService; | 17 | import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService; |
17 | import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; | 18 | import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; |
18 | import org.thingsboard.server.service.yunteng.media.TkVideoControlService; | 19 | import org.thingsboard.server.service.yunteng.media.TkVideoControlService; |
@@ -57,21 +58,140 @@ public class ZLMediaKitHookController extends BaseController { | @@ -57,21 +58,140 @@ public class ZLMediaKitHookController extends BaseController { | ||
57 | @ResponseBody | 58 | @ResponseBody |
58 | @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") | 59 | @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") |
59 | @ApiOperation(value = "流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流") | 60 | @ApiOperation(value = "流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流") |
60 | - public JsonNode onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) throws ThingsboardException { | 61 | + public JsonNode onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) |
62 | + throws ThingsboardException { | ||
61 | JsonNode result = tkMediaServerService.zlmOnStreamNoneReader(param); | 63 | JsonNode result = tkMediaServerService.zlmOnStreamNoneReader(param); |
62 | - if(result.has(FastIotConstants.ZLMediaBody.CHANNEL_ID) &&result.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)){ | 64 | + if (result.has(FastIotConstants.ZLMediaBody.CHANNEL_ID) |
65 | + && result.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)) { | ||
63 | String channelId = result.get(FastIotConstants.ZLMediaBody.CHANNEL_ID).asText(); | 66 | String channelId = result.get(FastIotConstants.ZLMediaBody.CHANNEL_ID).asText(); |
64 | String cameraCode = result.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText(); | 67 | String cameraCode = result.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText(); |
65 | - VideoChanelDTO chanelDTO = tkVideoChannelService.findVideoChannelById(cameraCode,channelId, null); | ||
66 | - controlService.byeCmdInSsrcTransaction(chanelDTO.getTenantId(), | ||
67 | - false, | ||
68 | - chanelDTO.getDeviceId(), | ||
69 | - cameraCode,channelId,result.get(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM).asText(), | ||
70 | - fromDeviceRpcResponse->{ | ||
71 | - | ||
72 | - }); | ||
73 | - tkVideoChannelService.updateVideoChannelStreamId(null, cameraCode, channelId);//storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); | 68 | + VideoChanelDTO chanelDTO = |
69 | + tkVideoChannelService.findVideoChannelById(cameraCode, channelId, null); | ||
70 | + controlService.byeCmdInSsrcTransaction( | ||
71 | + chanelDTO.getTenantId(), | ||
72 | + false, | ||
73 | + chanelDTO.getDeviceId(), | ||
74 | + cameraCode, | ||
75 | + channelId, | ||
76 | + result.get(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM).asText(), | ||
77 | + fromDeviceRpcResponse -> {}); | ||
78 | + tkVideoChannelService.updateVideoChannelStreamId( | ||
79 | + null, | ||
80 | + cameraCode, | ||
81 | + channelId); // storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); | ||
74 | } | 82 | } |
75 | return result; | 83 | return result; |
76 | } | 84 | } |
85 | + | ||
86 | + /** 流未找到事件,用户可以在此事件触发时,立即去拉流,这样可以实现按需拉流;此事件对回复不敏感。 */ | ||
87 | + @ResponseBody | ||
88 | + @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8") | ||
89 | + public DeferredResult<HookResult> onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param) { | ||
90 | + // log.error("WEBHOOK流未找到【on_stream_not_found】,API参数【{}】",JSONObject.toJSONString(param)); | ||
91 | + | ||
92 | + DeferredResult<HookResult> defaultResult = new DeferredResult<>(); | ||
93 | + | ||
94 | + // MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); | ||
95 | + // if (!userSetting.isAutoApplyPlay() || mediaInfo == null) { | ||
96 | + // defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), | ||
97 | + // ErrorCode.ERROR404.getMsg())); | ||
98 | + // return defaultResult; | ||
99 | + // } | ||
100 | + // | ||
101 | + // if ("rtp".equals(param.getApp())) { | ||
102 | + // String[] s = param.getStream().split("_"); | ||
103 | + // if (!mediaInfo.isRtpEnable() || s.length != 2) { | ||
104 | + // defaultResult.setResult(HookResult.SUCCESS()); | ||
105 | + // return defaultResult; | ||
106 | + // } | ||
107 | + // String deviceId = s[0]; | ||
108 | + // String channelId = s[1]; | ||
109 | + // Device device = redisCatchStorage.getDevice(deviceId); | ||
110 | + // if (device == null) { | ||
111 | + // defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), | ||
112 | + // ErrorCode.ERROR404.getMsg())); | ||
113 | + // return defaultResult; | ||
114 | + // } | ||
115 | + // DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | ||
116 | + // if (deviceChannel == null) { | ||
117 | + // defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), | ||
118 | + // ErrorCode.ERROR404.getMsg())); | ||
119 | + // return defaultResult; | ||
120 | + // } | ||
121 | + // logger.info("[ZLM HOOK] 流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(), | ||
122 | + // param.getSchema(), param.getApp(), param.getStream()); | ||
123 | + // RequestMessage msg = new RequestMessage(); | ||
124 | + // String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; | ||
125 | + // boolean exist = resultHolder.exist(key, null); | ||
126 | + // msg.setKey(key); | ||
127 | + // String uuid = UUID.randomUUID().toString(); | ||
128 | + // msg.setId(uuid); | ||
129 | + // DeferredResult<HookResult> result = new | ||
130 | + // DeferredResult<>(userSetting.getPlayTimeout().longValue()); | ||
131 | + // DeferredResultEx<HookResult> deferredResultEx = new DeferredResultEx<>(result); | ||
132 | + // | ||
133 | + // result.onTimeout(() -> { | ||
134 | + // logger.info("点播接口等待超时"); | ||
135 | + // // 释放rtpserver | ||
136 | + // msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); | ||
137 | + // resultHolder.invokeResult(msg); | ||
138 | + // }); | ||
139 | + // // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误 | ||
140 | + // deferredResultEx.setFilter(result1 -> { | ||
141 | + // WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>) result1; | ||
142 | + // HookResult resultForEnd = new HookResult(); | ||
143 | + // resultForEnd.setCode(wvpResult1.getCode()); | ||
144 | + // resultForEnd.setMsg(wvpResult1.getMsg()); | ||
145 | + // return resultForEnd; | ||
146 | + // }); | ||
147 | + // | ||
148 | + // // 录像查询以channelId作为deviceId查询 | ||
149 | + // resultHolder.put(key, uuid, deferredResultEx); | ||
150 | + // | ||
151 | + // if (!exist) { | ||
152 | + // playService.play(mediaInfo, deviceId, channelId, null, eventResult -> { | ||
153 | + // msg.setData(new HookResult(eventResult.statusCode, eventResult.msg)); | ||
154 | + // resultHolder.invokeResult(msg); | ||
155 | + // }, null); | ||
156 | + // } | ||
157 | + // return result; | ||
158 | + // } else { | ||
159 | + // // 拉流代理 | ||
160 | + // StreamProxyItem streamProxyByAppAndStream = | ||
161 | + // streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); | ||
162 | + // if (streamProxyByAppAndStream != null && | ||
163 | + // streamProxyByAppAndStream.isEnable_disable_none_reader()) { | ||
164 | + // streamProxyService.start(param.getApp(), param.getStream()); | ||
165 | + // } | ||
166 | + // DeferredResult<HookResult> result = new DeferredResult<>(); | ||
167 | + // result.setResult(HookResult.SUCCESS()); | ||
168 | + // return result; | ||
169 | + // } | ||
170 | + return defaultResult; | ||
171 | + } | ||
172 | + | ||
173 | + /** 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。 */ | ||
174 | + @ResponseBody | ||
175 | + @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8") | ||
176 | + public HookResult onServerStarted( | ||
177 | + HttpServletRequest request, @RequestBody JSONObject jsonObject) { | ||
178 | + // | ||
179 | + // log.error("WEBHOOK服务器已启动【on_server_started】,请求对象【{}】,API参数【{}】",JSONObject.toJSONString(request),jsonObject); | ||
180 | + // jsonObject.put("ip", request.getRemoteAddr()); | ||
181 | + // ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject); | ||
182 | + // zlmServerConfig.setIp(request.getRemoteAddr()); | ||
183 | + // logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId()); | ||
184 | + // taskExecutor.execute(() -> { | ||
185 | + // List<ZlmHttpHookSubscribe.Event> subscribes = | ||
186 | + // this.subscribe.getSubscribes(HookType.on_server_started); | ||
187 | + // if (subscribes != null && subscribes.size() > 0) { | ||
188 | + // for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | ||
189 | + // subscribe.response(null, jsonObject); | ||
190 | + // } | ||
191 | + // } | ||
192 | + // mediaServerService.zlmServerOnline(zlmServerConfig); | ||
193 | + // }); | ||
194 | + | ||
195 | + return HookResult.SUCCESS(); | ||
196 | + } | ||
77 | } | 197 | } |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2022 The Thingsboard Authors | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | * | 3 | * |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | 4 | + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
5 | + * except in compliance with the License. You may obtain a copy of the License at | ||
7 | * | 6 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | 7 | + * <p>http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | 8 | * |
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | 9 | + * <p>Unless required by applicable law or agreed to in writing, software distributed under the |
10 | + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
11 | + * express or implied. See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | 12 | * limitations under the License. |
15 | */ | 13 | */ |
16 | package org.thingsboard.server.service.transport; | 14 | package org.thingsboard.server.service.transport; |
@@ -37,7 +35,6 @@ import java.util.concurrent.locks.ReentrantLock; | @@ -37,7 +35,6 @@ import java.util.concurrent.locks.ReentrantLock; | ||
37 | import java.util.stream.Collectors; | 35 | import java.util.stream.Collectors; |
38 | import lombok.RequiredArgsConstructor; | 36 | import lombok.RequiredArgsConstructor; |
39 | import lombok.extern.slf4j.Slf4j; | 37 | import lombok.extern.slf4j.Slf4j; |
40 | -import org.apache.zookeeper.Op; | ||
41 | import org.springframework.stereotype.Service; | 38 | import org.springframework.stereotype.Service; |
42 | import org.thingsboard.common.util.JacksonUtil; | 39 | import org.thingsboard.common.util.JacksonUtil; |
43 | import org.thingsboard.server.cache.ota.OtaPackageDataCache; | 40 | import org.thingsboard.server.cache.ota.OtaPackageDataCache; |
@@ -74,13 +71,15 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | @@ -74,13 +71,15 @@ import org.thingsboard.server.common.data.relation.EntityRelation; | ||
74 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 71 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
75 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 72 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
76 | import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; | 73 | import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; |
74 | +import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | ||
77 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 75 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
78 | import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | 76 | import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; |
79 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; | 77 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; |
78 | +import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; | ||
80 | import org.thingsboard.server.common.data.yunteng.dto.sip.SipDeviceDTO; | 79 | import org.thingsboard.server.common.data.yunteng.dto.sip.SipDeviceDTO; |
81 | -import org.thingsboard.server.common.data.yunteng.dto.sip.SsrcTransactionDTO; | ||
82 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; | 80 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; |
83 | import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum; | 81 | import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum; |
82 | +import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; | ||
84 | import org.thingsboard.server.common.msg.EncryptionUtil; | 83 | import org.thingsboard.server.common.msg.EncryptionUtil; |
85 | import org.thingsboard.server.common.msg.TbMsg; | 84 | import org.thingsboard.server.common.msg.TbMsg; |
86 | import org.thingsboard.server.common.msg.TbMsgDataType; | 85 | import org.thingsboard.server.common.msg.TbMsgDataType; |
@@ -99,6 +98,7 @@ import org.thingsboard.server.dao.yunteng.entities.TkVideoChannelEntity; | @@ -99,6 +98,7 @@ import org.thingsboard.server.dao.yunteng.entities.TkVideoChannelEntity; | ||
99 | import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService; | 98 | import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService; |
100 | import org.thingsboard.server.dao.yunteng.service.TkDeviceService; | 99 | import org.thingsboard.server.dao.yunteng.service.TkDeviceService; |
101 | import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerNodeService; | 100 | import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerNodeService; |
101 | +import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService; | ||
102 | import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; | 102 | import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; |
103 | import org.thingsboard.server.gen.transport.TransportProtos; | 103 | import org.thingsboard.server.gen.transport.TransportProtos; |
104 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; | 104 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; |
@@ -126,650 +126,891 @@ import org.thingsboard.server.service.install.DefaultSystemDataLoaderService; | @@ -126,650 +126,891 @@ import org.thingsboard.server.service.install.DefaultSystemDataLoaderService; | ||
126 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; | 126 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
127 | import org.thingsboard.server.service.resource.TbResourceService; | 127 | import org.thingsboard.server.service.resource.TbResourceService; |
128 | 128 | ||
129 | -/** | ||
130 | - * Created by ashvayka on 05.10.18. | ||
131 | - */ | 129 | +/** Created by ashvayka on 05.10.18. */ |
132 | @Slf4j | 130 | @Slf4j |
133 | @Service | 131 | @Service |
134 | @TbCoreComponent | 132 | @TbCoreComponent |
135 | @RequiredArgsConstructor | 133 | @RequiredArgsConstructor |
136 | public class DefaultTransportApiService implements TransportApiService { | 134 | public class DefaultTransportApiService implements TransportApiService { |
137 | 135 | ||
138 | - private static final ObjectMapper mapper = new ObjectMapper(); | ||
139 | - | ||
140 | - private final TbDeviceProfileCache deviceProfileCache; | ||
141 | - private final TbTenantProfileCache tenantProfileCache; | ||
142 | - private final TbApiUsageStateService apiUsageStateService; | ||
143 | - private final DeviceService deviceService; | ||
144 | - private final TkDeviceService ytDeviceService; | ||
145 | - private final TkDeviceScriptService scriptService; | ||
146 | - private final TkVideoChannelService channelService; | ||
147 | - private final TkMediaServerNodeService mediaServerNodeService; | ||
148 | - private final VideoStreamSessionManager videoStreamSessionManager; | ||
149 | - | ||
150 | - private final RelationService relationService; | ||
151 | - private final DeviceCredentialsService deviceCredentialsService; | ||
152 | - private final DbCallbackExecutorService dbCallbackExecutorService; | ||
153 | - private final TbClusterService tbClusterService; | ||
154 | - private final DataDecodingEncodingService dataDecodingEncodingService; | ||
155 | - private final DeviceProvisionService deviceProvisionService; | ||
156 | - private final TbResourceService resourceService; | ||
157 | - private final OtaPackageService otaPackageService; | ||
158 | - private final OtaPackageDataCache otaPackageDataCache; | ||
159 | - | ||
160 | - private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>(); | ||
161 | - | ||
162 | - private static boolean checkIsMqttCredentials(DeviceCredentials credentials) { | ||
163 | - return credentials != null && DeviceCredentialsType.MQTT_BASIC.equals(credentials.getCredentialsType()); | 136 | + private static final ObjectMapper mapper = new ObjectMapper(); |
137 | + | ||
138 | + private final TbDeviceProfileCache deviceProfileCache; | ||
139 | + private final TbTenantProfileCache tenantProfileCache; | ||
140 | + private final TbApiUsageStateService apiUsageStateService; | ||
141 | + private final DeviceService deviceService; | ||
142 | + private final TkDeviceService ytDeviceService; | ||
143 | + private final TkDeviceScriptService scriptService; | ||
144 | + private final TkVideoChannelService channelService; | ||
145 | + private final TkMediaServerNodeService mediaServerNodeService; | ||
146 | + private final VideoStreamSessionManager videoStreamSessionManager; | ||
147 | + private final TkMediaServerService mediaServerService; | ||
148 | + private final ZLMediaKitRestFulUtils zlMediaKitRestFulUtils; | ||
149 | + | ||
150 | + private final RelationService relationService; | ||
151 | + private final DeviceCredentialsService deviceCredentialsService; | ||
152 | + private final DbCallbackExecutorService dbCallbackExecutorService; | ||
153 | + private final TbClusterService tbClusterService; | ||
154 | + private final DataDecodingEncodingService dataDecodingEncodingService; | ||
155 | + private final DeviceProvisionService deviceProvisionService; | ||
156 | + private final TbResourceService resourceService; | ||
157 | + private final OtaPackageService otaPackageService; | ||
158 | + private final OtaPackageDataCache otaPackageDataCache; | ||
159 | + | ||
160 | + private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = | ||
161 | + new ConcurrentHashMap<>(); | ||
162 | + | ||
163 | + private static boolean checkIsMqttCredentials(DeviceCredentials credentials) { | ||
164 | + return credentials != null | ||
165 | + && DeviceCredentialsType.MQTT_BASIC.equals(credentials.getCredentialsType()); | ||
166 | + } | ||
167 | + | ||
168 | + @Override | ||
169 | + public ListenableFuture<TbProtoQueueMsg<TransportApiResponseMsg>> handle( | ||
170 | + TbProtoQueueMsg<TransportApiRequestMsg> tbProtoQueueMsg) { | ||
171 | + TransportApiRequestMsg transportApiRequestMsg = tbProtoQueueMsg.getValue(); | ||
172 | + ListenableFuture<TransportApiResponseMsg> result = null; | ||
173 | + | ||
174 | + if (transportApiRequestMsg.hasValidateTokenRequestMsg()) { | ||
175 | + ValidateDeviceTokenRequestMsg msg = transportApiRequestMsg.getValidateTokenRequestMsg(); | ||
176 | + result = validateCredentials(msg.getToken(), DeviceCredentialsType.ACCESS_TOKEN); | ||
177 | + } else if (transportApiRequestMsg.hasValidateBasicMqttCredRequestMsg()) { | ||
178 | + TransportProtos.ValidateBasicMqttCredRequestMsg msg = | ||
179 | + transportApiRequestMsg.getValidateBasicMqttCredRequestMsg(); | ||
180 | + result = validateCredentials(msg); | ||
181 | + } else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) { | ||
182 | + ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg(); | ||
183 | + result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE); | ||
184 | + } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) { | ||
185 | + result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg()); | ||
186 | + } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { | ||
187 | + result = handle(transportApiRequestMsg.getEntityProfileRequestMsg()); | ||
188 | + } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) { | ||
189 | + result = handle(transportApiRequestMsg.getLwM2MRequestMsg()); | ||
190 | + } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) { | ||
191 | + ValidateDeviceLwM2MCredentialsRequestMsg msg = | ||
192 | + transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg(); | ||
193 | + result = validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS); | ||
194 | + } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { | ||
195 | + result = handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()); | ||
196 | + } else if (transportApiRequestMsg.hasResourceRequestMsg()) { | ||
197 | + result = handle(transportApiRequestMsg.getResourceRequestMsg()); | ||
198 | + } else if (transportApiRequestMsg.hasSnmpDevicesRequestMsg()) { | ||
199 | + result = handle(transportApiRequestMsg.getSnmpDevicesRequestMsg()); | ||
200 | + } else if (transportApiRequestMsg.hasDeviceRequestMsg()) { | ||
201 | + result = handle(transportApiRequestMsg.getDeviceRequestMsg()); | ||
202 | + } else if (transportApiRequestMsg.hasDeviceCredentialsRequestMsg()) { | ||
203 | + result = handle(transportApiRequestMsg.getDeviceCredentialsRequestMsg()); | ||
204 | + } else if (transportApiRequestMsg.hasOtaPackageRequestMsg()) { | ||
205 | + result = handle(transportApiRequestMsg.getOtaPackageRequestMsg()); | ||
164 | } | 206 | } |
165 | 207 | ||
166 | - @Override | ||
167 | - public ListenableFuture<TbProtoQueueMsg<TransportApiResponseMsg>> handle(TbProtoQueueMsg<TransportApiRequestMsg> tbProtoQueueMsg) { | ||
168 | - TransportApiRequestMsg transportApiRequestMsg = tbProtoQueueMsg.getValue(); | ||
169 | - ListenableFuture<TransportApiResponseMsg> result = null; | ||
170 | - | ||
171 | - if (transportApiRequestMsg.hasValidateTokenRequestMsg()) { | ||
172 | - ValidateDeviceTokenRequestMsg msg = transportApiRequestMsg.getValidateTokenRequestMsg(); | ||
173 | - result = validateCredentials(msg.getToken(), DeviceCredentialsType.ACCESS_TOKEN); | ||
174 | - } else if (transportApiRequestMsg.hasValidateBasicMqttCredRequestMsg()) { | ||
175 | - TransportProtos.ValidateBasicMqttCredRequestMsg msg = transportApiRequestMsg.getValidateBasicMqttCredRequestMsg(); | ||
176 | - result = validateCredentials(msg); | ||
177 | - } else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) { | ||
178 | - ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg(); | ||
179 | - result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE); | ||
180 | - } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) { | ||
181 | - result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg()); | ||
182 | - } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) { | ||
183 | - result = handle(transportApiRequestMsg.getEntityProfileRequestMsg()); | ||
184 | - } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) { | ||
185 | - result = handle(transportApiRequestMsg.getLwM2MRequestMsg()); | ||
186 | - } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) { | ||
187 | - ValidateDeviceLwM2MCredentialsRequestMsg msg = transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg(); | ||
188 | - result = validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS); | ||
189 | - } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) { | ||
190 | - result = handle(transportApiRequestMsg.getProvisionDeviceRequestMsg()); | ||
191 | - } else if (transportApiRequestMsg.hasResourceRequestMsg()) { | ||
192 | - result = handle(transportApiRequestMsg.getResourceRequestMsg()); | ||
193 | - } else if (transportApiRequestMsg.hasSnmpDevicesRequestMsg()) { | ||
194 | - result = handle(transportApiRequestMsg.getSnmpDevicesRequestMsg()); | ||
195 | - } else if (transportApiRequestMsg.hasDeviceRequestMsg()) { | ||
196 | - result = handle(transportApiRequestMsg.getDeviceRequestMsg()); | ||
197 | - } else if (transportApiRequestMsg.hasDeviceCredentialsRequestMsg()) { | ||
198 | - result = handle(transportApiRequestMsg.getDeviceCredentialsRequestMsg()); | ||
199 | - } else if (transportApiRequestMsg.hasOtaPackageRequestMsg()) { | ||
200 | - result = handle(transportApiRequestMsg.getOtaPackageRequestMsg()); | ||
201 | - } | ||
202 | - | ||
203 | - //Thingskit function | ||
204 | - else if (transportApiRequestMsg.hasScript()) { | ||
205 | - result = handle(transportApiRequestMsg.getScript()); | ||
206 | - } | ||
207 | - else if (transportApiRequestMsg.hasGbt28181RequestMsg()) { | ||
208 | - result = handleGbt(transportApiRequestMsg.getGbt28181RequestMsg()); | ||
209 | - } | ||
210 | - | ||
211 | - | ||
212 | - return Futures.transform(Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture), | ||
213 | - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), | ||
214 | - MoreExecutors.directExecutor()); | 208 | + // Thingskit function |
209 | + else if (transportApiRequestMsg.hasScript()) { | ||
210 | + result = handle(transportApiRequestMsg.getScript()); | ||
211 | + } else if (transportApiRequestMsg.hasGbt28181RequestMsg()) { | ||
212 | + result = handleGbt(transportApiRequestMsg.getGbt28181RequestMsg()); | ||
213 | + } else if (transportApiRequestMsg.hasGbt28181MediaServerMsg()) { | ||
214 | + result = handleGbtMedia(transportApiRequestMsg.getGbt28181MediaServerMsg()); | ||
215 | } | 215 | } |
216 | 216 | ||
217 | - private ListenableFuture<TransportApiResponseMsg> validateCredentials(String credentialsId, DeviceCredentialsType credentialsType) { | ||
218 | - //TODO: Make async and enable caching | ||
219 | - DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(credentialsId); | ||
220 | - if (credentials != null && credentials.getCredentialsType() == credentialsType) { | ||
221 | - return getDeviceInfo(credentials); | ||
222 | - } else { | ||
223 | - return getEmptyTransportApiResponseFuture(); | ||
224 | - } | 217 | + return Futures.transform( |
218 | + Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture), | ||
219 | + value -> | ||
220 | + new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()), | ||
221 | + MoreExecutors.directExecutor()); | ||
222 | + } | ||
223 | + | ||
224 | + private ListenableFuture<TransportApiResponseMsg> validateCredentials( | ||
225 | + String credentialsId, DeviceCredentialsType credentialsType) { | ||
226 | + // TODO: Make async and enable caching | ||
227 | + DeviceCredentials credentials = | ||
228 | + deviceCredentialsService.findDeviceCredentialsByCredentialsId(credentialsId); | ||
229 | + if (credentials != null && credentials.getCredentialsType() == credentialsType) { | ||
230 | + return getDeviceInfo(credentials); | ||
231 | + } else { | ||
232 | + return getEmptyTransportApiResponseFuture(); | ||
225 | } | 233 | } |
226 | - | ||
227 | - private ListenableFuture<TransportApiResponseMsg> validateCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) { | ||
228 | - DeviceCredentials credentials; | ||
229 | - if (StringUtils.isEmpty(mqtt.getUserName())) { | ||
230 | - credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash(mqtt.getClientId())); | ||
231 | - if (credentials != null) { | ||
232 | - return getDeviceInfo(credentials); | ||
233 | - } else { | ||
234 | - return getEmptyTransportApiResponseFuture(); | ||
235 | - } | 234 | + } |
235 | + | ||
236 | + private ListenableFuture<TransportApiResponseMsg> validateCredentials( | ||
237 | + TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) { | ||
238 | + DeviceCredentials credentials; | ||
239 | + if (StringUtils.isEmpty(mqtt.getUserName())) { | ||
240 | + credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash(mqtt.getClientId())); | ||
241 | + if (credentials != null) { | ||
242 | + return getDeviceInfo(credentials); | ||
243 | + } else { | ||
244 | + return getEmptyTransportApiResponseFuture(); | ||
245 | + } | ||
246 | + } else { | ||
247 | + credentials = | ||
248 | + deviceCredentialsService.findDeviceCredentialsByCredentialsId( | ||
249 | + EncryptionUtil.getSha3Hash("|", mqtt.getClientId(), mqtt.getUserName())); | ||
250 | + if (checkIsMqttCredentials(credentials)) { | ||
251 | + var validationResult = validateMqttCredentials(mqtt, credentials); | ||
252 | + if (VALID.equals(validationResult)) { | ||
253 | + return getDeviceInfo(credentials); | ||
254 | + } else if (PASSWORD_MISMATCH.equals(validationResult)) { | ||
255 | + return getEmptyTransportApiResponseFuture(); | ||
236 | } else { | 256 | } else { |
237 | - credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId( | ||
238 | - EncryptionUtil.getSha3Hash("|", mqtt.getClientId(), mqtt.getUserName())); | ||
239 | - if (checkIsMqttCredentials(credentials)) { | ||
240 | - var validationResult = validateMqttCredentials(mqtt, credentials); | ||
241 | - if (VALID.equals(validationResult)) { | ||
242 | - return getDeviceInfo(credentials); | ||
243 | - } else if (PASSWORD_MISMATCH.equals(validationResult)) { | ||
244 | - return getEmptyTransportApiResponseFuture(); | ||
245 | - } else { | ||
246 | - return validateUserNameCredentials(mqtt); | ||
247 | - } | ||
248 | - } else { | ||
249 | - return validateUserNameCredentials(mqtt); | ||
250 | - } | 257 | + return validateUserNameCredentials(mqtt); |
251 | } | 258 | } |
259 | + } else { | ||
260 | + return validateUserNameCredentials(mqtt); | ||
261 | + } | ||
252 | } | 262 | } |
253 | - | ||
254 | - private ListenableFuture<TransportApiResponseMsg> validateUserNameCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) { | ||
255 | - DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName()); | ||
256 | - if (credentials != null) { | ||
257 | - switch (credentials.getCredentialsType()) { | ||
258 | - case ACCESS_TOKEN: | ||
259 | - return getDeviceInfo(credentials); | ||
260 | - case MQTT_BASIC: | ||
261 | - if (VALID.equals(validateMqttCredentials(mqtt, credentials))) { | ||
262 | - return getDeviceInfo(credentials); | ||
263 | - } else { | ||
264 | - return getEmptyTransportApiResponseFuture(); | ||
265 | - } | ||
266 | - } | ||
267 | - } | ||
268 | - return getEmptyTransportApiResponseFuture(); | 263 | + } |
264 | + | ||
265 | + private ListenableFuture<TransportApiResponseMsg> validateUserNameCredentials( | ||
266 | + TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) { | ||
267 | + DeviceCredentials credentials = | ||
268 | + deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName()); | ||
269 | + if (credentials != null) { | ||
270 | + switch (credentials.getCredentialsType()) { | ||
271 | + case ACCESS_TOKEN: | ||
272 | + return getDeviceInfo(credentials); | ||
273 | + case MQTT_BASIC: | ||
274 | + if (VALID.equals(validateMqttCredentials(mqtt, credentials))) { | ||
275 | + return getDeviceInfo(credentials); | ||
276 | + } else { | ||
277 | + return getEmptyTransportApiResponseFuture(); | ||
278 | + } | ||
279 | + } | ||
269 | } | 280 | } |
270 | - | ||
271 | - private DeviceCredentials checkMqttCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, String credId) { | ||
272 | - return checkMqttCredentials(clientCred, deviceCredentialsService.findDeviceCredentialsByCredentialsId(credId)); | 281 | + return getEmptyTransportApiResponseFuture(); |
282 | + } | ||
283 | + | ||
284 | + private DeviceCredentials checkMqttCredentials( | ||
285 | + TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, String credId) { | ||
286 | + return checkMqttCredentials( | ||
287 | + clientCred, deviceCredentialsService.findDeviceCredentialsByCredentialsId(credId)); | ||
288 | + } | ||
289 | + | ||
290 | + private DeviceCredentials checkMqttCredentials( | ||
291 | + TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, | ||
292 | + DeviceCredentials deviceCredentials) { | ||
293 | + if (deviceCredentials != null | ||
294 | + && deviceCredentials.getCredentialsType() == DeviceCredentialsType.MQTT_BASIC) { | ||
295 | + if (VALID.equals(validateMqttCredentials(clientCred, deviceCredentials))) { | ||
296 | + return deviceCredentials; | ||
297 | + } | ||
273 | } | 298 | } |
274 | - | ||
275 | - private DeviceCredentials checkMqttCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, DeviceCredentials deviceCredentials) { | ||
276 | - if (deviceCredentials != null && deviceCredentials.getCredentialsType() == DeviceCredentialsType.MQTT_BASIC) { | ||
277 | - if (VALID.equals(validateMqttCredentials(clientCred, deviceCredentials))) { | ||
278 | - return deviceCredentials; | ||
279 | - } | ||
280 | - } | ||
281 | - return null; | 299 | + return null; |
300 | + } | ||
301 | + | ||
302 | + private BasicCredentialsValidationResult validateMqttCredentials( | ||
303 | + TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, | ||
304 | + DeviceCredentials deviceCredentials) { | ||
305 | + BasicMqttCredentials dbCred = | ||
306 | + JacksonUtil.fromString(deviceCredentials.getCredentialsValue(), BasicMqttCredentials.class); | ||
307 | + if (!StringUtils.isEmpty(dbCred.getClientId()) | ||
308 | + && !dbCred.getClientId().equals(clientCred.getClientId())) { | ||
309 | + return BasicCredentialsValidationResult.HASH_MISMATCH; | ||
282 | } | 310 | } |
283 | - | ||
284 | - private BasicCredentialsValidationResult validateMqttCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, DeviceCredentials deviceCredentials) { | ||
285 | - BasicMqttCredentials dbCred = JacksonUtil.fromString(deviceCredentials.getCredentialsValue(), BasicMqttCredentials.class); | ||
286 | - if (!StringUtils.isEmpty(dbCred.getClientId()) && !dbCred.getClientId().equals(clientCred.getClientId())) { | ||
287 | - return BasicCredentialsValidationResult.HASH_MISMATCH; | ||
288 | - } | ||
289 | - if (!StringUtils.isEmpty(dbCred.getUserName()) && !dbCred.getUserName().equals(clientCred.getUserName())) { | ||
290 | - return BasicCredentialsValidationResult.HASH_MISMATCH; | ||
291 | - } | ||
292 | - if (!StringUtils.isEmpty(dbCred.getPassword())) { | ||
293 | - if (StringUtils.isEmpty(clientCred.getPassword())) { | ||
294 | - return BasicCredentialsValidationResult.PASSWORD_MISMATCH; | ||
295 | - } else { | ||
296 | - return dbCred.getPassword().equals(clientCred.getPassword()) ? VALID : BasicCredentialsValidationResult.PASSWORD_MISMATCH; | ||
297 | - } | ||
298 | - } | ||
299 | - return VALID; | 311 | + if (!StringUtils.isEmpty(dbCred.getUserName()) |
312 | + && !dbCred.getUserName().equals(clientCred.getUserName())) { | ||
313 | + return BasicCredentialsValidationResult.HASH_MISMATCH; | ||
300 | } | 314 | } |
301 | - | ||
302 | - private ListenableFuture<TransportApiResponseMsg> handle(GetOrCreateDeviceFromGatewayRequestMsg requestMsg) { | ||
303 | - DeviceId gatewayId = new DeviceId(new UUID(requestMsg.getGatewayIdMSB(), requestMsg.getGatewayIdLSB())); | ||
304 | - ListenableFuture<Device> gatewayFuture = deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, gatewayId); | ||
305 | - return Futures.transform(gatewayFuture, gateway -> { | ||
306 | - Lock deviceCreationLock = deviceCreationLocks.computeIfAbsent(requestMsg.getDeviceName(), id -> new ReentrantLock()); | ||
307 | - deviceCreationLock.lock(); | ||
308 | - try { | ||
309 | - | ||
310 | - //Thingskit function | ||
311 | - String slaveName = requestMsg.getDeviceName(); | ||
312 | - if(gateway.getDeviceData().getTransportConfiguration().getType() == DeviceTransportType.TCP) { | ||
313 | - DeviceDTO iotDev = ytDeviceService.findSlaveDevice(gateway.getTenantId().getId().toString() | ||
314 | - , gateway.getId().getId().toString() | ||
315 | - ,slaveName); | ||
316 | - if(iotDev == null ){ | ||
317 | - GetOrCreateDeviceFromGatewayResponseMsg.Builder builder = GetOrCreateDeviceFromGatewayResponseMsg.newBuilder(); | ||
318 | - return TransportApiResponseMsg.newBuilder() | ||
319 | - .setGetOrCreateDeviceResponseMsg(builder.build()) | ||
320 | - .build(); | ||
321 | - } | ||
322 | - slaveName = iotDev.getName(); | ||
323 | - } | ||
324 | - | ||
325 | - Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), slaveName); | ||
326 | - | ||
327 | - if (device == null) { | ||
328 | - TenantId tenantId = gateway.getTenantId(); | ||
329 | - device = new Device(); | ||
330 | - device.setTenantId(tenantId); | ||
331 | - device.setName(requestMsg.getDeviceName()); | ||
332 | - device.setType(requestMsg.getDeviceType()); | ||
333 | - device.setCustomerId(gateway.getCustomerId()); | ||
334 | - DeviceProfile deviceProfile = deviceProfileCache.findOrCreateDeviceProfile(gateway.getTenantId(), DefaultSystemDataLoaderService.DEFAULT_DEVICE_TYPE); | ||
335 | - device.setDeviceProfileId(deviceProfile.getId()); | ||
336 | - ObjectNode additionalInfo = JacksonUtil.newObjectNode(); | ||
337 | - additionalInfo.put(DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString()); | ||
338 | - device.setAdditionalInfo(additionalInfo); | ||
339 | - Device savedDevice = deviceService.saveDevice(device); | ||
340 | - | ||
341 | - | ||
342 | - //Thingskit function | ||
343 | - ytDeviceService.saveSlaveDevice(savedDevice.getId().getId().toString(), savedDevice.getName(),deviceProfile.getId().getId().toString(), gateway.getId().getId().toString(),gateway.getCreatedTime()); | ||
344 | - | ||
345 | - | ||
346 | - tbClusterService.onDeviceUpdated(savedDevice, null); | ||
347 | - device = savedDevice; | ||
348 | - | ||
349 | - relationService.saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(gateway.getId(), device.getId(), "Created")); | ||
350 | - | ||
351 | - TbMsgMetaData metaData = new TbMsgMetaData(); | ||
352 | - CustomerId customerId = gateway.getCustomerId(); | ||
353 | - if (customerId != null && !customerId.isNullUid()) { | ||
354 | - metaData.putValue("customerId", customerId.toString()); | ||
355 | - } | ||
356 | - metaData.putValue("gatewayId", gatewayId.toString()); | ||
357 | - | ||
358 | - DeviceId deviceId = device.getId(); | ||
359 | - ObjectNode entityNode = mapper.valueToTree(device); | ||
360 | - TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, customerId, metaData, TbMsgDataType.JSON, mapper.writeValueAsString(entityNode)); | ||
361 | - tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, null); | ||
362 | - } else { | ||
363 | - JsonNode deviceAdditionalInfo = device.getAdditionalInfo(); | ||
364 | - if (deviceAdditionalInfo == null) { | ||
365 | - deviceAdditionalInfo = JacksonUtil.newObjectNode(); | ||
366 | - } | ||
367 | - if (deviceAdditionalInfo.isObject() && | ||
368 | - (!deviceAdditionalInfo.has(DataConstants.LAST_CONNECTED_GATEWAY) | ||
369 | - || !gatewayId.toString().equals(deviceAdditionalInfo.get(DataConstants.LAST_CONNECTED_GATEWAY).asText()))) { | ||
370 | - ObjectNode newDeviceAdditionalInfo = (ObjectNode) deviceAdditionalInfo; | ||
371 | - newDeviceAdditionalInfo.put(DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString()); | ||
372 | - Device savedDevice = deviceService.saveDevice(device); | ||
373 | - tbClusterService.onDeviceUpdated(savedDevice, device); | ||
374 | - } | ||
375 | - } | ||
376 | - GetOrCreateDeviceFromGatewayResponseMsg.Builder builder = GetOrCreateDeviceFromGatewayResponseMsg.newBuilder() | ||
377 | - .setDeviceInfo(getDeviceInfoProto(device)); | ||
378 | - DeviceProfile deviceProfile = deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId()); | ||
379 | - if (deviceProfile != null) { | ||
380 | - builder.setProfileBody(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile))); | ||
381 | - } else { | ||
382 | - log.warn("[{}] Failed to find device profile [{}] for device. ", device.getId(), device.getDeviceProfileId()); | ||
383 | - } | 315 | + if (!StringUtils.isEmpty(dbCred.getPassword())) { |
316 | + if (StringUtils.isEmpty(clientCred.getPassword())) { | ||
317 | + return BasicCredentialsValidationResult.PASSWORD_MISMATCH; | ||
318 | + } else { | ||
319 | + return dbCred.getPassword().equals(clientCred.getPassword()) | ||
320 | + ? VALID | ||
321 | + : BasicCredentialsValidationResult.PASSWORD_MISMATCH; | ||
322 | + } | ||
323 | + } | ||
324 | + return VALID; | ||
325 | + } | ||
326 | + | ||
327 | + private ListenableFuture<TransportApiResponseMsg> handle( | ||
328 | + GetOrCreateDeviceFromGatewayRequestMsg requestMsg) { | ||
329 | + DeviceId gatewayId = | ||
330 | + new DeviceId(new UUID(requestMsg.getGatewayIdMSB(), requestMsg.getGatewayIdLSB())); | ||
331 | + ListenableFuture<Device> gatewayFuture = | ||
332 | + deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, gatewayId); | ||
333 | + return Futures.transform( | ||
334 | + gatewayFuture, | ||
335 | + gateway -> { | ||
336 | + Lock deviceCreationLock = | ||
337 | + deviceCreationLocks.computeIfAbsent( | ||
338 | + requestMsg.getDeviceName(), id -> new ReentrantLock()); | ||
339 | + deviceCreationLock.lock(); | ||
340 | + try { | ||
341 | + | ||
342 | + // Thingskit function | ||
343 | + String slaveName = requestMsg.getDeviceName(); | ||
344 | + if (gateway.getDeviceData().getTransportConfiguration().getType() | ||
345 | + == DeviceTransportType.TCP) { | ||
346 | + DeviceDTO iotDev = | ||
347 | + ytDeviceService.findSlaveDevice( | ||
348 | + gateway.getTenantId().getId().toString(), | ||
349 | + gateway.getId().getId().toString(), | ||
350 | + slaveName); | ||
351 | + if (iotDev == null) { | ||
352 | + GetOrCreateDeviceFromGatewayResponseMsg.Builder builder = | ||
353 | + GetOrCreateDeviceFromGatewayResponseMsg.newBuilder(); | ||
384 | return TransportApiResponseMsg.newBuilder() | 354 | return TransportApiResponseMsg.newBuilder() |
385 | - .setGetOrCreateDeviceResponseMsg(builder.build()) | ||
386 | - .build(); | ||
387 | - } catch (JsonProcessingException e) { | ||
388 | - log.warn("[{}] Failed to lookup device by gateway id and name: [{}]", gatewayId, requestMsg.getDeviceName(), e); | ||
389 | - throw new RuntimeException(e); | ||
390 | - } finally { | ||
391 | - deviceCreationLock.unlock(); | 355 | + .setGetOrCreateDeviceResponseMsg(builder.build()) |
356 | + .build(); | ||
357 | + } | ||
358 | + slaveName = iotDev.getName(); | ||
392 | } | 359 | } |
393 | - }, dbCallbackExecutorService); | ||
394 | - } | ||
395 | 360 | ||
396 | - private ListenableFuture<TransportApiResponseMsg> handle(ProvisionDeviceRequestMsg requestMsg) { | ||
397 | - ListenableFuture<ProvisionResponse> provisionResponseFuture = null; | ||
398 | - try { | ||
399 | - provisionResponseFuture = Futures.immediateFuture(deviceProvisionService.provisionDevice( | ||
400 | - new ProvisionRequest( | ||
401 | - requestMsg.getDeviceName(), | ||
402 | - requestMsg.getCredentialsType() != null ? DeviceCredentialsType.valueOf(requestMsg.getCredentialsType().name()) : null, | ||
403 | - new ProvisionDeviceCredentialsData(requestMsg.getCredentialsDataProto().getValidateDeviceTokenRequestMsg().getToken(), | ||
404 | - requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getClientId(), | ||
405 | - requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getUserName(), | ||
406 | - requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getPassword(), | ||
407 | - requestMsg.getCredentialsDataProto().getValidateDeviceX509CertRequestMsg().getHash()), | ||
408 | - new ProvisionDeviceProfileCredentials( | ||
409 | - requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceKey(), | ||
410 | - requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceSecret())))); | ||
411 | - } catch (ProvisionFailedException e) { | ||
412 | - return Futures.immediateFuture(getTransportApiResponseMsg( | ||
413 | - new DeviceCredentials(), | ||
414 | - TransportProtos.ResponseStatus.valueOf(e.getMessage()))); | ||
415 | - } | ||
416 | - return Futures.transform(provisionResponseFuture, provisionResponse -> getTransportApiResponseMsg(provisionResponse.getDeviceCredentials(), TransportProtos.ResponseStatus.SUCCESS), | ||
417 | - dbCallbackExecutorService); | ||
418 | - } | 361 | + Device device = |
362 | + deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), slaveName); | ||
419 | 363 | ||
420 | - private TransportApiResponseMsg getTransportApiResponseMsg(DeviceCredentials | ||
421 | - deviceCredentials, TransportProtos.ResponseStatus status) { | ||
422 | - if (!status.equals(TransportProtos.ResponseStatus.SUCCESS)) { | ||
423 | - return TransportApiResponseMsg.newBuilder().setProvisionDeviceResponseMsg(TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build()).build(); | ||
424 | - } | ||
425 | - TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse = TransportProtos.ProvisionDeviceResponseMsg.newBuilder() | ||
426 | - .setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name())) | ||
427 | - .setStatus(status); | ||
428 | - switch (deviceCredentials.getCredentialsType()) { | ||
429 | - case ACCESS_TOKEN: | ||
430 | - provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId()); | ||
431 | - break; | ||
432 | - case MQTT_BASIC: | ||
433 | - case X509_CERTIFICATE: | ||
434 | - case LWM2M_CREDENTIALS: | ||
435 | - provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsValue()); | ||
436 | - break; | ||
437 | - } | ||
438 | - | ||
439 | - return TransportApiResponseMsg.newBuilder() | ||
440 | - .setProvisionDeviceResponseMsg(provisionResponse.build()) | 364 | + if (device == null) { |
365 | + TenantId tenantId = gateway.getTenantId(); | ||
366 | + device = new Device(); | ||
367 | + device.setTenantId(tenantId); | ||
368 | + device.setName(requestMsg.getDeviceName()); | ||
369 | + device.setType(requestMsg.getDeviceType()); | ||
370 | + device.setCustomerId(gateway.getCustomerId()); | ||
371 | + DeviceProfile deviceProfile = | ||
372 | + deviceProfileCache.findOrCreateDeviceProfile( | ||
373 | + gateway.getTenantId(), DefaultSystemDataLoaderService.DEFAULT_DEVICE_TYPE); | ||
374 | + device.setDeviceProfileId(deviceProfile.getId()); | ||
375 | + ObjectNode additionalInfo = JacksonUtil.newObjectNode(); | ||
376 | + additionalInfo.put(DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString()); | ||
377 | + device.setAdditionalInfo(additionalInfo); | ||
378 | + Device savedDevice = deviceService.saveDevice(device); | ||
379 | + | ||
380 | + // Thingskit function | ||
381 | + ytDeviceService.saveSlaveDevice( | ||
382 | + savedDevice.getId().getId().toString(), | ||
383 | + savedDevice.getName(), | ||
384 | + deviceProfile.getId().getId().toString(), | ||
385 | + gateway.getId().getId().toString(), | ||
386 | + gateway.getCreatedTime()); | ||
387 | + | ||
388 | + tbClusterService.onDeviceUpdated(savedDevice, null); | ||
389 | + device = savedDevice; | ||
390 | + | ||
391 | + relationService.saveRelationAsync( | ||
392 | + TenantId.SYS_TENANT_ID, | ||
393 | + new EntityRelation(gateway.getId(), device.getId(), "Created")); | ||
394 | + | ||
395 | + TbMsgMetaData metaData = new TbMsgMetaData(); | ||
396 | + CustomerId customerId = gateway.getCustomerId(); | ||
397 | + if (customerId != null && !customerId.isNullUid()) { | ||
398 | + metaData.putValue("customerId", customerId.toString()); | ||
399 | + } | ||
400 | + metaData.putValue("gatewayId", gatewayId.toString()); | ||
401 | + | ||
402 | + DeviceId deviceId = device.getId(); | ||
403 | + ObjectNode entityNode = mapper.valueToTree(device); | ||
404 | + TbMsg tbMsg = | ||
405 | + TbMsg.newMsg( | ||
406 | + DataConstants.ENTITY_CREATED, | ||
407 | + deviceId, | ||
408 | + customerId, | ||
409 | + metaData, | ||
410 | + TbMsgDataType.JSON, | ||
411 | + mapper.writeValueAsString(entityNode)); | ||
412 | + tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, null); | ||
413 | + } else { | ||
414 | + JsonNode deviceAdditionalInfo = device.getAdditionalInfo(); | ||
415 | + if (deviceAdditionalInfo == null) { | ||
416 | + deviceAdditionalInfo = JacksonUtil.newObjectNode(); | ||
417 | + } | ||
418 | + if (deviceAdditionalInfo.isObject() | ||
419 | + && (!deviceAdditionalInfo.has(DataConstants.LAST_CONNECTED_GATEWAY) | ||
420 | + || !gatewayId | ||
421 | + .toString() | ||
422 | + .equals( | ||
423 | + deviceAdditionalInfo | ||
424 | + .get(DataConstants.LAST_CONNECTED_GATEWAY) | ||
425 | + .asText()))) { | ||
426 | + ObjectNode newDeviceAdditionalInfo = (ObjectNode) deviceAdditionalInfo; | ||
427 | + newDeviceAdditionalInfo.put( | ||
428 | + DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString()); | ||
429 | + Device savedDevice = deviceService.saveDevice(device); | ||
430 | + tbClusterService.onDeviceUpdated(savedDevice, device); | ||
431 | + } | ||
432 | + } | ||
433 | + GetOrCreateDeviceFromGatewayResponseMsg.Builder builder = | ||
434 | + GetOrCreateDeviceFromGatewayResponseMsg.newBuilder() | ||
435 | + .setDeviceInfo(getDeviceInfoProto(device)); | ||
436 | + DeviceProfile deviceProfile = | ||
437 | + deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId()); | ||
438 | + if (deviceProfile != null) { | ||
439 | + builder.setProfileBody( | ||
440 | + ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile))); | ||
441 | + } else { | ||
442 | + log.warn( | ||
443 | + "[{}] Failed to find device profile [{}] for device. ", | ||
444 | + device.getId(), | ||
445 | + device.getDeviceProfileId()); | ||
446 | + } | ||
447 | + return TransportApiResponseMsg.newBuilder() | ||
448 | + .setGetOrCreateDeviceResponseMsg(builder.build()) | ||
441 | .build(); | 449 | .build(); |
450 | + } catch (JsonProcessingException e) { | ||
451 | + log.warn( | ||
452 | + "[{}] Failed to lookup device by gateway id and name: [{}]", | ||
453 | + gatewayId, | ||
454 | + requestMsg.getDeviceName(), | ||
455 | + e); | ||
456 | + throw new RuntimeException(e); | ||
457 | + } finally { | ||
458 | + deviceCreationLock.unlock(); | ||
459 | + } | ||
460 | + }, | ||
461 | + dbCallbackExecutorService); | ||
462 | + } | ||
463 | + | ||
464 | + private ListenableFuture<TransportApiResponseMsg> handle(ProvisionDeviceRequestMsg requestMsg) { | ||
465 | + ListenableFuture<ProvisionResponse> provisionResponseFuture = null; | ||
466 | + try { | ||
467 | + provisionResponseFuture = | ||
468 | + Futures.immediateFuture( | ||
469 | + deviceProvisionService.provisionDevice( | ||
470 | + new ProvisionRequest( | ||
471 | + requestMsg.getDeviceName(), | ||
472 | + requestMsg.getCredentialsType() != null | ||
473 | + ? DeviceCredentialsType.valueOf(requestMsg.getCredentialsType().name()) | ||
474 | + : null, | ||
475 | + new ProvisionDeviceCredentialsData( | ||
476 | + requestMsg | ||
477 | + .getCredentialsDataProto() | ||
478 | + .getValidateDeviceTokenRequestMsg() | ||
479 | + .getToken(), | ||
480 | + requestMsg | ||
481 | + .getCredentialsDataProto() | ||
482 | + .getValidateBasicMqttCredRequestMsg() | ||
483 | + .getClientId(), | ||
484 | + requestMsg | ||
485 | + .getCredentialsDataProto() | ||
486 | + .getValidateBasicMqttCredRequestMsg() | ||
487 | + .getUserName(), | ||
488 | + requestMsg | ||
489 | + .getCredentialsDataProto() | ||
490 | + .getValidateBasicMqttCredRequestMsg() | ||
491 | + .getPassword(), | ||
492 | + requestMsg | ||
493 | + .getCredentialsDataProto() | ||
494 | + .getValidateDeviceX509CertRequestMsg() | ||
495 | + .getHash()), | ||
496 | + new ProvisionDeviceProfileCredentials( | ||
497 | + requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceKey(), | ||
498 | + requestMsg | ||
499 | + .getProvisionDeviceCredentialsMsg() | ||
500 | + .getProvisionDeviceSecret())))); | ||
501 | + } catch (ProvisionFailedException e) { | ||
502 | + return Futures.immediateFuture( | ||
503 | + getTransportApiResponseMsg( | ||
504 | + new DeviceCredentials(), TransportProtos.ResponseStatus.valueOf(e.getMessage()))); | ||
442 | } | 505 | } |
443 | - | ||
444 | - private ListenableFuture<TransportApiResponseMsg> handle(GetEntityProfileRequestMsg requestMsg) { | ||
445 | - EntityType entityType = EntityType.valueOf(requestMsg.getEntityType()); | ||
446 | - UUID entityUuid = new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB()); | ||
447 | - GetEntityProfileResponseMsg.Builder builder = GetEntityProfileResponseMsg.newBuilder(); | ||
448 | - if (entityType.equals(EntityType.DEVICE_PROFILE)) { | ||
449 | - DeviceProfileId deviceProfileId = new DeviceProfileId(entityUuid); | ||
450 | - DeviceProfile deviceProfile = deviceProfileCache.find(deviceProfileId); | ||
451 | - builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile))); | ||
452 | - } else if (entityType.equals(EntityType.TENANT)) { | ||
453 | - TenantId tenantId = TenantId.fromUUID(entityUuid); | ||
454 | - TenantProfile tenantProfile = tenantProfileCache.get(tenantId); | ||
455 | - ApiUsageState state = apiUsageStateService.getApiUsageState(tenantId); | ||
456 | - builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(tenantProfile))); | ||
457 | - builder.setApiState(ByteString.copyFrom(dataDecodingEncodingService.encode(state))); | ||
458 | - } else { | ||
459 | - throw new RuntimeException("Invalid entity profile request: " + entityType); | ||
460 | - } | ||
461 | - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); | 506 | + return Futures.transform( |
507 | + provisionResponseFuture, | ||
508 | + provisionResponse -> | ||
509 | + getTransportApiResponseMsg( | ||
510 | + provisionResponse.getDeviceCredentials(), TransportProtos.ResponseStatus.SUCCESS), | ||
511 | + dbCallbackExecutorService); | ||
512 | + } | ||
513 | + | ||
514 | + private TransportApiResponseMsg getTransportApiResponseMsg( | ||
515 | + DeviceCredentials deviceCredentials, TransportProtos.ResponseStatus status) { | ||
516 | + if (!status.equals(TransportProtos.ResponseStatus.SUCCESS)) { | ||
517 | + return TransportApiResponseMsg.newBuilder() | ||
518 | + .setProvisionDeviceResponseMsg( | ||
519 | + TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build()) | ||
520 | + .build(); | ||
462 | } | 521 | } |
463 | - | ||
464 | - private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceRequestMsg requestMsg) { | ||
465 | - DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
466 | - Device device = deviceService.findDeviceById(TenantId.SYS_TENANT_ID, deviceId); | ||
467 | - | ||
468 | - TransportApiResponseMsg responseMsg; | ||
469 | - if (device != null) { | ||
470 | - UUID deviceProfileId = device.getDeviceProfileId().getId(); | ||
471 | - responseMsg = TransportApiResponseMsg.newBuilder() | ||
472 | - .setDeviceResponseMsg(TransportProtos.GetDeviceResponseMsg.newBuilder() | ||
473 | - .setDeviceProfileIdMSB(deviceProfileId.getMostSignificantBits()) | ||
474 | - .setDeviceProfileIdLSB(deviceProfileId.getLeastSignificantBits()) | ||
475 | - .setDeviceTransportConfiguration(ByteString.copyFrom( | ||
476 | - dataDecodingEncodingService.encode(device.getDeviceData().getTransportConfiguration()) | ||
477 | - ))) | ||
478 | - .build(); | ||
479 | - } else { | ||
480 | - responseMsg = TransportApiResponseMsg.getDefaultInstance(); | ||
481 | - } | ||
482 | - | ||
483 | - return Futures.immediateFuture(responseMsg); | 522 | + TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse = |
523 | + TransportProtos.ProvisionDeviceResponseMsg.newBuilder() | ||
524 | + .setCredentialsType( | ||
525 | + TransportProtos.CredentialsType.valueOf( | ||
526 | + deviceCredentials.getCredentialsType().name())) | ||
527 | + .setStatus(status); | ||
528 | + switch (deviceCredentials.getCredentialsType()) { | ||
529 | + case ACCESS_TOKEN: | ||
530 | + provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId()); | ||
531 | + break; | ||
532 | + case MQTT_BASIC: | ||
533 | + case X509_CERTIFICATE: | ||
534 | + case LWM2M_CREDENTIALS: | ||
535 | + provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsValue()); | ||
536 | + break; | ||
484 | } | 537 | } |
485 | 538 | ||
486 | - private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceCredentialsRequestMsg requestMsg) { | ||
487 | - DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
488 | - DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, deviceId); | ||
489 | - | ||
490 | - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder() | ||
491 | - .setDeviceCredentialsResponseMsg(TransportProtos.GetDeviceCredentialsResponseMsg.newBuilder() | ||
492 | - .setDeviceCredentialsData(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceCredentials)))) | ||
493 | - .build()); | 539 | + return TransportApiResponseMsg.newBuilder() |
540 | + .setProvisionDeviceResponseMsg(provisionResponse.build()) | ||
541 | + .build(); | ||
542 | + } | ||
543 | + | ||
544 | + private ListenableFuture<TransportApiResponseMsg> handle(GetEntityProfileRequestMsg requestMsg) { | ||
545 | + EntityType entityType = EntityType.valueOf(requestMsg.getEntityType()); | ||
546 | + UUID entityUuid = new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB()); | ||
547 | + GetEntityProfileResponseMsg.Builder builder = GetEntityProfileResponseMsg.newBuilder(); | ||
548 | + if (entityType.equals(EntityType.DEVICE_PROFILE)) { | ||
549 | + DeviceProfileId deviceProfileId = new DeviceProfileId(entityUuid); | ||
550 | + DeviceProfile deviceProfile = deviceProfileCache.find(deviceProfileId); | ||
551 | + builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile))); | ||
552 | + } else if (entityType.equals(EntityType.TENANT)) { | ||
553 | + TenantId tenantId = TenantId.fromUUID(entityUuid); | ||
554 | + TenantProfile tenantProfile = tenantProfileCache.get(tenantId); | ||
555 | + ApiUsageState state = apiUsageStateService.getApiUsageState(tenantId); | ||
556 | + builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(tenantProfile))); | ||
557 | + builder.setApiState(ByteString.copyFrom(dataDecodingEncodingService.encode(state))); | ||
558 | + } else { | ||
559 | + throw new RuntimeException("Invalid entity profile request: " + entityType); | ||
494 | } | 560 | } |
495 | - | ||
496 | - | ||
497 | - private ListenableFuture<TransportApiResponseMsg> handle(GetResourceRequestMsg requestMsg) { | ||
498 | - TenantId tenantId = TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); | ||
499 | - ResourceType resourceType = ResourceType.valueOf(requestMsg.getResourceType()); | ||
500 | - String resourceKey = requestMsg.getResourceKey(); | ||
501 | - TransportProtos.GetResourceResponseMsg.Builder builder = TransportProtos.GetResourceResponseMsg.newBuilder(); | ||
502 | - TbResource resource = resourceService.getResource(tenantId, resourceType, resourceKey); | ||
503 | - | ||
504 | - if (resource == null && !tenantId.equals(TenantId.SYS_TENANT_ID)) { | ||
505 | - resource = resourceService.getResource(TenantId.SYS_TENANT_ID, resourceType, resourceKey); | ||
506 | - } | ||
507 | - | ||
508 | - if (resource != null) { | ||
509 | - builder.setResource(ByteString.copyFrom(dataDecodingEncodingService.encode(resource))); | ||
510 | - } | ||
511 | - | ||
512 | - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setResourceResponseMsg(builder).build()); | 561 | + return Futures.immediateFuture( |
562 | + TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); | ||
563 | + } | ||
564 | + | ||
565 | + private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceRequestMsg requestMsg) { | ||
566 | + DeviceId deviceId = | ||
567 | + new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
568 | + Device device = deviceService.findDeviceById(TenantId.SYS_TENANT_ID, deviceId); | ||
569 | + | ||
570 | + TransportApiResponseMsg responseMsg; | ||
571 | + if (device != null) { | ||
572 | + UUID deviceProfileId = device.getDeviceProfileId().getId(); | ||
573 | + responseMsg = | ||
574 | + TransportApiResponseMsg.newBuilder() | ||
575 | + .setDeviceResponseMsg( | ||
576 | + TransportProtos.GetDeviceResponseMsg.newBuilder() | ||
577 | + .setDeviceProfileIdMSB(deviceProfileId.getMostSignificantBits()) | ||
578 | + .setDeviceProfileIdLSB(deviceProfileId.getLeastSignificantBits()) | ||
579 | + .setDeviceTransportConfiguration( | ||
580 | + ByteString.copyFrom( | ||
581 | + dataDecodingEncodingService.encode( | ||
582 | + device.getDeviceData().getTransportConfiguration())))) | ||
583 | + .build(); | ||
584 | + } else { | ||
585 | + responseMsg = TransportApiResponseMsg.getDefaultInstance(); | ||
513 | } | 586 | } |
514 | 587 | ||
515 | - private ListenableFuture<TransportApiResponseMsg> handle(GetSnmpDevicesRequestMsg requestMsg) { | ||
516 | - PageLink pageLink = new PageLink(requestMsg.getPageSize(), requestMsg.getPage()); | ||
517 | - PageData<UUID> result = deviceService.findDevicesIdsByDeviceProfileTransportType(DeviceTransportType.SNMP, pageLink); | ||
518 | - | ||
519 | - GetSnmpDevicesResponseMsg responseMsg = GetSnmpDevicesResponseMsg.newBuilder() | ||
520 | - .addAllIds(result.getData().stream() | ||
521 | - .map(UUID::toString) | ||
522 | - .collect(Collectors.toList())) | ||
523 | - .setHasNextPage(result.hasNext()) | ||
524 | - .build(); | 588 | + return Futures.immediateFuture(responseMsg); |
589 | + } | ||
590 | + | ||
591 | + private ListenableFuture<TransportApiResponseMsg> handle( | ||
592 | + GetDeviceCredentialsRequestMsg requestMsg) { | ||
593 | + DeviceId deviceId = | ||
594 | + new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
595 | + DeviceCredentials deviceCredentials = | ||
596 | + deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, deviceId); | ||
597 | + | ||
598 | + return Futures.immediateFuture( | ||
599 | + TransportApiResponseMsg.newBuilder() | ||
600 | + .setDeviceCredentialsResponseMsg( | ||
601 | + TransportProtos.GetDeviceCredentialsResponseMsg.newBuilder() | ||
602 | + .setDeviceCredentialsData( | ||
603 | + ByteString.copyFrom(dataDecodingEncodingService.encode(deviceCredentials)))) | ||
604 | + .build()); | ||
605 | + } | ||
606 | + | ||
607 | + private ListenableFuture<TransportApiResponseMsg> handle(GetResourceRequestMsg requestMsg) { | ||
608 | + TenantId tenantId = | ||
609 | + TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); | ||
610 | + ResourceType resourceType = ResourceType.valueOf(requestMsg.getResourceType()); | ||
611 | + String resourceKey = requestMsg.getResourceKey(); | ||
612 | + TransportProtos.GetResourceResponseMsg.Builder builder = | ||
613 | + TransportProtos.GetResourceResponseMsg.newBuilder(); | ||
614 | + TbResource resource = resourceService.getResource(tenantId, resourceType, resourceKey); | ||
615 | + | ||
616 | + if (resource == null && !tenantId.equals(TenantId.SYS_TENANT_ID)) { | ||
617 | + resource = resourceService.getResource(TenantId.SYS_TENANT_ID, resourceType, resourceKey); | ||
618 | + } | ||
525 | 619 | ||
526 | - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder() | ||
527 | - .setSnmpDevicesResponseMsg(responseMsg) | ||
528 | - .build()); | 620 | + if (resource != null) { |
621 | + builder.setResource(ByteString.copyFrom(dataDecodingEncodingService.encode(resource))); | ||
529 | } | 622 | } |
530 | 623 | ||
531 | - private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceCredentials credentials) { | ||
532 | - return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, credentials.getDeviceId()), device -> { | ||
533 | - if (device == null) { | ||
534 | - log.trace("[{}] Failed to lookup device by id", credentials.getDeviceId()); | ||
535 | - return getEmptyTransportApiResponse(); | 624 | + return Futures.immediateFuture( |
625 | + TransportApiResponseMsg.newBuilder().setResourceResponseMsg(builder).build()); | ||
626 | + } | ||
627 | + | ||
628 | + private ListenableFuture<TransportApiResponseMsg> handle(GetSnmpDevicesRequestMsg requestMsg) { | ||
629 | + PageLink pageLink = new PageLink(requestMsg.getPageSize(), requestMsg.getPage()); | ||
630 | + PageData<UUID> result = | ||
631 | + deviceService.findDevicesIdsByDeviceProfileTransportType( | ||
632 | + DeviceTransportType.SNMP, pageLink); | ||
633 | + | ||
634 | + GetSnmpDevicesResponseMsg responseMsg = | ||
635 | + GetSnmpDevicesResponseMsg.newBuilder() | ||
636 | + .addAllIds(result.getData().stream().map(UUID::toString).collect(Collectors.toList())) | ||
637 | + .setHasNextPage(result.hasNext()) | ||
638 | + .build(); | ||
639 | + | ||
640 | + return Futures.immediateFuture( | ||
641 | + TransportApiResponseMsg.newBuilder().setSnmpDevicesResponseMsg(responseMsg).build()); | ||
642 | + } | ||
643 | + | ||
644 | + private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceCredentials credentials) { | ||
645 | + return Futures.transform( | ||
646 | + deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, credentials.getDeviceId()), | ||
647 | + device -> { | ||
648 | + if (device == null) { | ||
649 | + log.trace("[{}] Failed to lookup device by id", credentials.getDeviceId()); | ||
650 | + return getEmptyTransportApiResponse(); | ||
651 | + } | ||
652 | + try { | ||
653 | + ValidateDeviceCredentialsResponseMsg.Builder builder = | ||
654 | + ValidateDeviceCredentialsResponseMsg.newBuilder(); | ||
655 | + builder.setDeviceInfo(getDeviceInfoProto(device)); | ||
656 | + DeviceProfile deviceProfile = | ||
657 | + deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId()); | ||
658 | + if (deviceProfile != null) { | ||
659 | + builder.setProfileBody( | ||
660 | + ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile))); | ||
661 | + } else { | ||
662 | + log.warn( | ||
663 | + "[{}] Failed to find device profile [{}] for device. ", | ||
664 | + device.getId(), | ||
665 | + device.getDeviceProfileId()); | ||
536 | } | 666 | } |
537 | - try { | ||
538 | - ValidateDeviceCredentialsResponseMsg.Builder builder = ValidateDeviceCredentialsResponseMsg.newBuilder(); | ||
539 | - builder.setDeviceInfo(getDeviceInfoProto(device)); | ||
540 | - DeviceProfile deviceProfile = deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId()); | ||
541 | - if (deviceProfile != null) { | ||
542 | - builder.setProfileBody(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile))); | ||
543 | - } else { | ||
544 | - log.warn("[{}] Failed to find device profile [{}] for device. ", device.getId(), device.getDeviceProfileId()); | ||
545 | - } | ||
546 | - if (!StringUtils.isEmpty(credentials.getCredentialsValue())) { | ||
547 | - builder.setCredentialsBody(credentials.getCredentialsValue()); | ||
548 | - } | ||
549 | - return TransportApiResponseMsg.newBuilder() | ||
550 | - .setValidateCredResponseMsg(builder.build()).build(); | ||
551 | - } catch (JsonProcessingException e) { | ||
552 | - log.warn("[{}] Failed to lookup device by id", credentials.getDeviceId(), e); | ||
553 | - return getEmptyTransportApiResponse(); | 667 | + if (!StringUtils.isEmpty(credentials.getCredentialsValue())) { |
668 | + builder.setCredentialsBody(credentials.getCredentialsValue()); | ||
554 | } | 669 | } |
555 | - }, MoreExecutors.directExecutor()); | 670 | + return TransportApiResponseMsg.newBuilder() |
671 | + .setValidateCredResponseMsg(builder.build()) | ||
672 | + .build(); | ||
673 | + } catch (JsonProcessingException e) { | ||
674 | + log.warn("[{}] Failed to lookup device by id", credentials.getDeviceId(), e); | ||
675 | + return getEmptyTransportApiResponse(); | ||
676 | + } | ||
677 | + }, | ||
678 | + MoreExecutors.directExecutor()); | ||
679 | + } | ||
680 | + | ||
681 | + private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException { | ||
682 | + DeviceInfoProto.Builder builder = | ||
683 | + DeviceInfoProto.newBuilder() | ||
684 | + .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits()) | ||
685 | + .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits()) | ||
686 | + .setCustomerIdMSB( | ||
687 | + Optional.ofNullable(device.getCustomerId()) | ||
688 | + .map(customerId -> customerId.getId().getMostSignificantBits()) | ||
689 | + .orElse(0L)) | ||
690 | + .setCustomerIdLSB( | ||
691 | + Optional.ofNullable(device.getCustomerId()) | ||
692 | + .map(customerId -> customerId.getId().getLeastSignificantBits()) | ||
693 | + .orElse(0L)) | ||
694 | + .setDeviceIdMSB(device.getId().getId().getMostSignificantBits()) | ||
695 | + .setDeviceIdLSB(device.getId().getId().getLeastSignificantBits()) | ||
696 | + .setDeviceName(device.getName()) | ||
697 | + .setDeviceType(device.getType()) | ||
698 | + .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits()) | ||
699 | + .setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits()) | ||
700 | + .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo())); | ||
701 | + | ||
702 | + PowerSavingConfiguration psmConfiguration = null; | ||
703 | + switch (device.getDeviceData().getTransportConfiguration().getType()) { | ||
704 | + case LWM2M: | ||
705 | + psmConfiguration = | ||
706 | + (Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration(); | ||
707 | + break; | ||
708 | + case COAP: | ||
709 | + psmConfiguration = | ||
710 | + (CoapDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration(); | ||
711 | + break; | ||
556 | } | 712 | } |
557 | 713 | ||
558 | - private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException { | ||
559 | - DeviceInfoProto.Builder builder = DeviceInfoProto.newBuilder() | ||
560 | - .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits()) | ||
561 | - .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits()) | ||
562 | - .setCustomerIdMSB(Optional.ofNullable(device.getCustomerId()).map(customerId -> customerId.getId().getMostSignificantBits()).orElse(0L)) | ||
563 | - .setCustomerIdLSB(Optional.ofNullable(device.getCustomerId()).map(customerId -> customerId.getId().getLeastSignificantBits()).orElse(0L)) | ||
564 | - .setDeviceIdMSB(device.getId().getId().getMostSignificantBits()) | ||
565 | - .setDeviceIdLSB(device.getId().getId().getLeastSignificantBits()) | ||
566 | - .setDeviceName(device.getName()) | ||
567 | - .setDeviceType(device.getType()) | ||
568 | - .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits()) | ||
569 | - .setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits()) | ||
570 | - .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo())); | ||
571 | - | ||
572 | - PowerSavingConfiguration psmConfiguration = null; | ||
573 | - switch (device.getDeviceData().getTransportConfiguration().getType()) { | ||
574 | - case LWM2M: | ||
575 | - psmConfiguration = (Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration(); | ||
576 | - break; | ||
577 | - case COAP: | ||
578 | - psmConfiguration = (CoapDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration(); | ||
579 | - break; | ||
580 | - } | ||
581 | - | ||
582 | - if (psmConfiguration != null) { | ||
583 | - PowerMode powerMode = psmConfiguration.getPowerMode(); | ||
584 | - if (powerMode != null) { | ||
585 | - builder.setPowerMode(powerMode.name()); | ||
586 | - if (powerMode.equals(PowerMode.PSM)) { | ||
587 | - builder.setPsmActivityTimer(checkLong(psmConfiguration.getPsmActivityTimer())); | ||
588 | - } else if (powerMode.equals(PowerMode.E_DRX)) { | ||
589 | - builder.setEdrxCycle(checkLong(psmConfiguration.getEdrxCycle())); | ||
590 | - builder.setPagingTransmissionWindow(checkLong(psmConfiguration.getPagingTransmissionWindow())); | ||
591 | - } | ||
592 | - } | 714 | + if (psmConfiguration != null) { |
715 | + PowerMode powerMode = psmConfiguration.getPowerMode(); | ||
716 | + if (powerMode != null) { | ||
717 | + builder.setPowerMode(powerMode.name()); | ||
718 | + if (powerMode.equals(PowerMode.PSM)) { | ||
719 | + builder.setPsmActivityTimer(checkLong(psmConfiguration.getPsmActivityTimer())); | ||
720 | + } else if (powerMode.equals(PowerMode.E_DRX)) { | ||
721 | + builder.setEdrxCycle(checkLong(psmConfiguration.getEdrxCycle())); | ||
722 | + builder.setPagingTransmissionWindow( | ||
723 | + checkLong(psmConfiguration.getPagingTransmissionWindow())); | ||
593 | } | 724 | } |
594 | - return builder.build(); | 725 | + } |
595 | } | 726 | } |
596 | - | ||
597 | - private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() { | ||
598 | - return Futures.immediateFuture(getEmptyTransportApiResponse()); | 727 | + return builder.build(); |
728 | + } | ||
729 | + | ||
730 | + private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() { | ||
731 | + return Futures.immediateFuture(getEmptyTransportApiResponse()); | ||
732 | + } | ||
733 | + | ||
734 | + private TransportApiResponseMsg getEmptyTransportApiResponse() { | ||
735 | + return TransportApiResponseMsg.newBuilder() | ||
736 | + .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance()) | ||
737 | + .build(); | ||
738 | + } | ||
739 | + | ||
740 | + private ListenableFuture<TransportApiResponseMsg> handle( | ||
741 | + TransportProtos.LwM2MRequestMsg requestMsg) { | ||
742 | + if (requestMsg.hasRegistrationMsg()) { | ||
743 | + return handleRegistration(requestMsg.getRegistrationMsg()); | ||
744 | + } else { | ||
745 | + return Futures.immediateFailedFuture(new RuntimeException("Not supported!")); | ||
599 | } | 746 | } |
600 | - | ||
601 | - private TransportApiResponseMsg getEmptyTransportApiResponse() { | ||
602 | - return TransportApiResponseMsg.newBuilder() | ||
603 | - .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance()).build(); | 747 | + } |
748 | + | ||
749 | + private ListenableFuture<TransportApiResponseMsg> handle( | ||
750 | + TransportProtos.GetOtaPackageRequestMsg requestMsg) { | ||
751 | + TenantId tenantId = | ||
752 | + TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); | ||
753 | + DeviceId deviceId = | ||
754 | + new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
755 | + OtaPackageType otaPackageType = OtaPackageType.valueOf(requestMsg.getType()); | ||
756 | + Device device = deviceService.findDeviceById(tenantId, deviceId); | ||
757 | + | ||
758 | + if (device == null) { | ||
759 | + return getEmptyTransportApiResponseFuture(); | ||
604 | } | 760 | } |
605 | 761 | ||
606 | - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.LwM2MRequestMsg requestMsg) { | ||
607 | - if (requestMsg.hasRegistrationMsg()) { | ||
608 | - return handleRegistration(requestMsg.getRegistrationMsg()); | ||
609 | - } else { | ||
610 | - return Futures.immediateFailedFuture(new RuntimeException("Not supported!")); | ||
611 | - } | ||
612 | - } | ||
613 | - | ||
614 | - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetOtaPackageRequestMsg requestMsg) { | ||
615 | - TenantId tenantId = TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); | ||
616 | - DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB())); | ||
617 | - OtaPackageType otaPackageType = OtaPackageType.valueOf(requestMsg.getType()); | ||
618 | - Device device = deviceService.findDeviceById(tenantId, deviceId); | ||
619 | - | ||
620 | - if (device == null) { | ||
621 | - return getEmptyTransportApiResponseFuture(); | ||
622 | - } | ||
623 | - | ||
624 | - OtaPackageId otaPackageId = OtaPackageUtil.getOtaPackageId(device, otaPackageType); | ||
625 | - if (otaPackageId == null) { | ||
626 | - DeviceProfile deviceProfile = deviceProfileCache.find(device.getDeviceProfileId()); | ||
627 | - otaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, otaPackageType); | ||
628 | - } | ||
629 | - | ||
630 | - TransportProtos.GetOtaPackageResponseMsg.Builder builder = TransportProtos.GetOtaPackageResponseMsg.newBuilder(); | ||
631 | - | ||
632 | - if (otaPackageId == null) { | ||
633 | - builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND); | ||
634 | - } else { | ||
635 | - OtaPackageInfo otaPackageInfo = otaPackageService.findOtaPackageInfoById(tenantId, otaPackageId); | ||
636 | - | ||
637 | - if (otaPackageInfo == null) { | ||
638 | - builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND); | ||
639 | - } else if (otaPackageInfo.hasUrl()) { | ||
640 | - builder.setResponseStatus(TransportProtos.ResponseStatus.FAILURE); | ||
641 | - log.trace("[{}] Can`t send OtaPackage with URL data!", otaPackageInfo.getId()); | ||
642 | - } else { | ||
643 | - builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS); | ||
644 | - builder.setOtaPackageIdMSB(otaPackageId.getId().getMostSignificantBits()); | ||
645 | - builder.setOtaPackageIdLSB(otaPackageId.getId().getLeastSignificantBits()); | ||
646 | - builder.setType(otaPackageInfo.getType().name()); | ||
647 | - builder.setTitle(otaPackageInfo.getTitle()); | ||
648 | - builder.setVersion(otaPackageInfo.getVersion()); | ||
649 | - builder.setFileName(otaPackageInfo.getFileName()); | ||
650 | - builder.setContentType(otaPackageInfo.getContentType()); | ||
651 | - if (!otaPackageDataCache.has(otaPackageId.toString())) { | ||
652 | - OtaPackage otaPackage = otaPackageService.findOtaPackageById(tenantId, otaPackageId); | ||
653 | - otaPackageDataCache.put(otaPackageId.toString(), otaPackage.getData().array()); | ||
654 | - } | ||
655 | - } | ||
656 | - } | ||
657 | - | ||
658 | - return Futures.immediateFuture( | ||
659 | - TransportApiResponseMsg.newBuilder() | ||
660 | - .setOtaPackageResponseMsg(builder.build()) | ||
661 | - .build()); | 762 | + OtaPackageId otaPackageId = OtaPackageUtil.getOtaPackageId(device, otaPackageType); |
763 | + if (otaPackageId == null) { | ||
764 | + DeviceProfile deviceProfile = deviceProfileCache.find(device.getDeviceProfileId()); | ||
765 | + otaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, otaPackageType); | ||
662 | } | 766 | } |
663 | 767 | ||
664 | - private ListenableFuture<TransportApiResponseMsg> handleRegistration | ||
665 | - (TransportProtos.LwM2MRegistrationRequestMsg msg) { | ||
666 | - TenantId tenantId = TenantId.fromUUID(UUID.fromString(msg.getTenantId())); | ||
667 | - String deviceName = msg.getEndpoint(); | ||
668 | - Lock deviceCreationLock = deviceCreationLocks.computeIfAbsent(deviceName, id -> new ReentrantLock()); | ||
669 | - deviceCreationLock.lock(); | ||
670 | - try { | ||
671 | - Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName); | ||
672 | - if (device == null) { | ||
673 | - device = new Device(); | ||
674 | - device.setTenantId(tenantId); | ||
675 | - device.setName(deviceName); | ||
676 | - device.setType("LwM2M"); | ||
677 | - device = deviceService.saveDevice(device); | ||
678 | - tbClusterService.onDeviceUpdated(device, null); | ||
679 | - } | ||
680 | - TransportProtos.LwM2MRegistrationResponseMsg registrationResponseMsg = | ||
681 | - TransportProtos.LwM2MRegistrationResponseMsg.newBuilder() | ||
682 | - .setDeviceInfo(getDeviceInfoProto(device)).build(); | ||
683 | - TransportProtos.LwM2MResponseMsg responseMsg = TransportProtos.LwM2MResponseMsg.newBuilder().setRegistrationMsg(registrationResponseMsg).build(); | ||
684 | - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setLwM2MResponseMsg(responseMsg).build()); | ||
685 | - } catch (JsonProcessingException e) { | ||
686 | - log.warn("[{}][{}] Failed to lookup device by gateway id and name", tenantId, deviceName, e); | ||
687 | - throw new RuntimeException(e); | ||
688 | - } finally { | ||
689 | - deviceCreationLock.unlock(); | 768 | + TransportProtos.GetOtaPackageResponseMsg.Builder builder = |
769 | + TransportProtos.GetOtaPackageResponseMsg.newBuilder(); | ||
770 | + | ||
771 | + if (otaPackageId == null) { | ||
772 | + builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND); | ||
773 | + } else { | ||
774 | + OtaPackageInfo otaPackageInfo = | ||
775 | + otaPackageService.findOtaPackageInfoById(tenantId, otaPackageId); | ||
776 | + | ||
777 | + if (otaPackageInfo == null) { | ||
778 | + builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND); | ||
779 | + } else if (otaPackageInfo.hasUrl()) { | ||
780 | + builder.setResponseStatus(TransportProtos.ResponseStatus.FAILURE); | ||
781 | + log.trace("[{}] Can`t send OtaPackage with URL data!", otaPackageInfo.getId()); | ||
782 | + } else { | ||
783 | + builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS); | ||
784 | + builder.setOtaPackageIdMSB(otaPackageId.getId().getMostSignificantBits()); | ||
785 | + builder.setOtaPackageIdLSB(otaPackageId.getId().getLeastSignificantBits()); | ||
786 | + builder.setType(otaPackageInfo.getType().name()); | ||
787 | + builder.setTitle(otaPackageInfo.getTitle()); | ||
788 | + builder.setVersion(otaPackageInfo.getVersion()); | ||
789 | + builder.setFileName(otaPackageInfo.getFileName()); | ||
790 | + builder.setContentType(otaPackageInfo.getContentType()); | ||
791 | + if (!otaPackageDataCache.has(otaPackageId.toString())) { | ||
792 | + OtaPackage otaPackage = otaPackageService.findOtaPackageById(tenantId, otaPackageId); | ||
793 | + otaPackageDataCache.put(otaPackageId.toString(), otaPackage.getData().array()); | ||
690 | } | 794 | } |
795 | + } | ||
691 | } | 796 | } |
692 | 797 | ||
693 | - private Long checkLong(Long l) { | ||
694 | - return l != null ? l : 0; | 798 | + return Futures.immediateFuture( |
799 | + TransportApiResponseMsg.newBuilder().setOtaPackageResponseMsg(builder.build()).build()); | ||
800 | + } | ||
801 | + | ||
802 | + private ListenableFuture<TransportApiResponseMsg> handleRegistration( | ||
803 | + TransportProtos.LwM2MRegistrationRequestMsg msg) { | ||
804 | + TenantId tenantId = TenantId.fromUUID(UUID.fromString(msg.getTenantId())); | ||
805 | + String deviceName = msg.getEndpoint(); | ||
806 | + Lock deviceCreationLock = | ||
807 | + deviceCreationLocks.computeIfAbsent(deviceName, id -> new ReentrantLock()); | ||
808 | + deviceCreationLock.lock(); | ||
809 | + try { | ||
810 | + Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName); | ||
811 | + if (device == null) { | ||
812 | + device = new Device(); | ||
813 | + device.setTenantId(tenantId); | ||
814 | + device.setName(deviceName); | ||
815 | + device.setType("LwM2M"); | ||
816 | + device = deviceService.saveDevice(device); | ||
817 | + tbClusterService.onDeviceUpdated(device, null); | ||
818 | + } | ||
819 | + TransportProtos.LwM2MRegistrationResponseMsg registrationResponseMsg = | ||
820 | + TransportProtos.LwM2MRegistrationResponseMsg.newBuilder() | ||
821 | + .setDeviceInfo(getDeviceInfoProto(device)) | ||
822 | + .build(); | ||
823 | + TransportProtos.LwM2MResponseMsg responseMsg = | ||
824 | + TransportProtos.LwM2MResponseMsg.newBuilder() | ||
825 | + .setRegistrationMsg(registrationResponseMsg) | ||
826 | + .build(); | ||
827 | + return Futures.immediateFuture( | ||
828 | + TransportApiResponseMsg.newBuilder().setLwM2MResponseMsg(responseMsg).build()); | ||
829 | + } catch (JsonProcessingException e) { | ||
830 | + log.warn("[{}][{}] Failed to lookup device by gateway id and name", tenantId, deviceName, e); | ||
831 | + throw new RuntimeException(e); | ||
832 | + } finally { | ||
833 | + deviceCreationLock.unlock(); | ||
695 | } | 834 | } |
696 | - | ||
697 | - | ||
698 | - | ||
699 | - //Thingskit function | ||
700 | - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.ScriptProto requestMsg) { | ||
701 | - List<TkDeviceScriptDTO> allScriptes = scriptService.getScriptes(); | ||
702 | - TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder(); | ||
703 | - allScriptes.forEach( | ||
704 | - item -> { | ||
705 | - UUID tenantId = UUID.fromString(item.getTenantId()); | ||
706 | - UUID id = UUID.fromString(item.getId()); | ||
707 | - responseBuilder.addScriptsResponseMsg( | ||
708 | - TransportProtos.ScriptProto.newBuilder() | ||
709 | - .setConvertJs(item.getConvertJs()) | ||
710 | - .setTenantIdLSB(tenantId.getLeastSignificantBits()) | ||
711 | - .setTenantIdMSB(tenantId.getMostSignificantBits()) | ||
712 | - .setScriptIdLSB(id.getLeastSignificantBits()) | ||
713 | - .setScriptIdMSB(id.getMostSignificantBits()) | ||
714 | - .setFunctionType(item.getScriptType().name()) | ||
715 | - .setStatus(item.getStatus())); | ||
716 | - }); | ||
717 | - return Futures.immediateFuture(responseBuilder.build()); | ||
718 | - } | ||
719 | - private ListenableFuture<TransportApiResponseMsg> handleGbt(TransportProtos.Gbt28181RequestMsg requestMsg) { | ||
720 | - TransportProtos.Gbt28181ResponseMsg.Builder responseMsgBuilder =TransportProtos.Gbt28181ResponseMsg.newBuilder(); | ||
721 | - String tenantId = new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()).toString(); | ||
722 | - String tbDeviceId = new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB()).toString(); | ||
723 | - String type = requestMsg.getContextType(); | ||
724 | - switch (VideoCmdEnum.valueOf(type)){ | ||
725 | - case DeviceInfo: | ||
726 | - Optional<SipDeviceDTO> camera = dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray()); | ||
727 | - camera.ifPresent(sip ->{ | ||
728 | - ytDeviceService.updateDeviceInfo(tenantId,tbDeviceId, FastIotConstants.DeviceAdditional.SIP,JacksonUtil.valueToTree(sip)); | ||
729 | - }); | ||
730 | - | ||
731 | - break; | ||
732 | - case Catalog: | ||
733 | - Optional<List<VideoChanelDTO>> allChannel = dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray()); | ||
734 | - allChannel.ifPresent(d->{ | ||
735 | - channelService.clearDeviceChannel(d.get(0).getCameraCode()); | ||
736 | - List<TkVideoChannelEntity> chanel= d.stream().map(item -> item.getEntity(TkVideoChannelEntity.class)).collect(Collectors.toList()); | ||
737 | - channelService.insertBatch(chanel,chanel.size()); | ||
738 | - }); | ||
739 | - break; | ||
740 | - default: | ||
741 | - release(tenantId,tbDeviceId); | ||
742 | - | ||
743 | - } | ||
744 | -// byte[] channaelMsgBytes = dataDecodingEncodingService.encode(channelDTO); | ||
745 | -// responseMsgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes)); | ||
746 | - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setGbt28181ResponseMsg(responseMsgBuilder.build()).build()); | 835 | + } |
836 | + | ||
837 | + private Long checkLong(Long l) { | ||
838 | + return l != null ? l : 0; | ||
839 | + } | ||
840 | + | ||
841 | + // Thingskit function | ||
842 | + private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.ScriptProto requestMsg) { | ||
843 | + List<TkDeviceScriptDTO> allScriptes = scriptService.getScriptes(); | ||
844 | + TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder(); | ||
845 | + allScriptes.forEach( | ||
846 | + item -> { | ||
847 | + UUID tenantId = UUID.fromString(item.getTenantId()); | ||
848 | + UUID id = UUID.fromString(item.getId()); | ||
849 | + responseBuilder.addScriptsResponseMsg( | ||
850 | + TransportProtos.ScriptProto.newBuilder() | ||
851 | + .setConvertJs(item.getConvertJs()) | ||
852 | + .setTenantIdLSB(tenantId.getLeastSignificantBits()) | ||
853 | + .setTenantIdMSB(tenantId.getMostSignificantBits()) | ||
854 | + .setScriptIdLSB(id.getLeastSignificantBits()) | ||
855 | + .setScriptIdMSB(id.getMostSignificantBits()) | ||
856 | + .setFunctionType(item.getScriptType().name()) | ||
857 | + .setStatus(item.getStatus())); | ||
858 | + }); | ||
859 | + return Futures.immediateFuture(responseBuilder.build()); | ||
860 | + } | ||
861 | + | ||
862 | + private ListenableFuture<TransportApiResponseMsg> handleGbt( | ||
863 | + TransportProtos.Gbt28181RequestMsg requestMsg) { | ||
864 | + TransportProtos.Gbt28181ResponseMsg.Builder responseMsgBuilder = | ||
865 | + TransportProtos.Gbt28181ResponseMsg.newBuilder(); | ||
866 | + String tenantId = new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()).toString(); | ||
867 | + String tbDeviceId = | ||
868 | + new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB()).toString(); | ||
869 | + String type = requestMsg.getContextType(); | ||
870 | + switch (VideoCmdEnum.valueOf(type)) { | ||
871 | + case DeviceInfo: | ||
872 | + Optional<SipDeviceDTO> camera = | ||
873 | + dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray()); | ||
874 | + camera.ifPresent( | ||
875 | + sip -> { | ||
876 | + ytDeviceService.updateDeviceInfo( | ||
877 | + tenantId, | ||
878 | + tbDeviceId, | ||
879 | + FastIotConstants.DeviceAdditional.SIP, | ||
880 | + JacksonUtil.valueToTree(sip)); | ||
881 | + }); | ||
882 | + | ||
883 | + break; | ||
884 | + case Catalog: | ||
885 | + Optional<List<VideoChanelDTO>> allChannel = | ||
886 | + dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray()); | ||
887 | + allChannel.ifPresent( | ||
888 | + d -> { | ||
889 | + channelService.clearDeviceChannel(d.get(0).getCameraCode()); | ||
890 | + List<TkVideoChannelEntity> chanel = | ||
891 | + d.stream() | ||
892 | + .map(item -> item.getEntity(TkVideoChannelEntity.class)) | ||
893 | + .collect(Collectors.toList()); | ||
894 | + channelService.insertBatch(chanel, chanel.size()); | ||
895 | + }); | ||
896 | + break; | ||
897 | + default: | ||
898 | + release(tenantId, tbDeviceId); | ||
747 | } | 899 | } |
748 | - private void release(String tenantId,String tbDeviceId){ | ||
749 | - DeviceDTO device = ytDeviceService.findDeviceInfoByTbDeviceId(tenantId,tbDeviceId); | ||
750 | - Optional.ofNullable(device).ifPresent(dev->{ | ||
751 | - JsonNode sip = dev.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP); | ||
752 | - if(!sip.isEmpty() && sip.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)){ | 900 | + // byte[] channaelMsgBytes = dataDecodingEncodingService.encode(channelDTO); |
901 | + // responseMsgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes)); | ||
902 | + return Futures.immediateFuture( | ||
903 | + TransportApiResponseMsg.newBuilder() | ||
904 | + .setGbt28181ResponseMsg(responseMsgBuilder.build()) | ||
905 | + .build()); | ||
906 | + } | ||
907 | + | ||
908 | + private void release(String tenantId, String tbDeviceId) { | ||
909 | + DeviceDTO device = ytDeviceService.findDeviceInfoByTbDeviceId(tenantId, tbDeviceId); | ||
910 | + Optional.ofNullable(device) | ||
911 | + .ifPresent( | ||
912 | + dev -> { | ||
913 | + JsonNode sip = dev.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP); | ||
914 | + if (!sip.isEmpty() && sip.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)) { | ||
753 | String cameraCode = sip.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText(); | 915 | String cameraCode = sip.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText(); |
754 | Optional<Set<String>> ssrcKeys = | 916 | Optional<Set<String>> ssrcKeys = |
755 | - videoStreamSessionManager.getSsrcTransactionCamaraKey(cameraCode); | ||
756 | - ssrcKeys.ifPresent(all ->{ | ||
757 | - all.forEach(fullKey->{ | ||
758 | - videoStreamSessionManager.getSsrcTransaction(fullKey).ifPresent(ssrcTransaction -> { | ||
759 | - mediaServerNodeService.releaseSsrc( | ||
760 | - ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); | ||
761 | - mediaServerNodeService.closeRTPServer( | ||
762 | - ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream()); | ||
763 | - videoStreamSessionManager.remove( | ||
764 | - cameraCode, ssrcTransaction.getChannelId(), | ||
765 | - ssrcTransaction.getStream()); | ||
766 | - }); | ||
767 | - | 917 | + videoStreamSessionManager.getSsrcTransactionCamaraKey(cameraCode); |
918 | + ssrcKeys.ifPresent( | ||
919 | + all -> { | ||
920 | + all.forEach( | ||
921 | + fullKey -> { | ||
922 | + videoStreamSessionManager | ||
923 | + .getSsrcTransaction(fullKey) | ||
924 | + .ifPresent( | ||
925 | + ssrcTransaction -> { | ||
926 | + mediaServerNodeService.releaseSsrc( | ||
927 | + ssrcTransaction.getMediaServerId(), | ||
928 | + ssrcTransaction.getSsrc()); | ||
929 | + mediaServerNodeService.closeRTPServer( | ||
930 | + ssrcTransaction.getMediaServerId(), | ||
931 | + ssrcTransaction.getStream()); | ||
932 | + videoStreamSessionManager.remove( | ||
933 | + cameraCode, | ||
934 | + ssrcTransaction.getChannelId(), | ||
935 | + ssrcTransaction.getStream()); | ||
936 | + }); | ||
937 | + }); | ||
768 | }); | 938 | }); |
769 | - }); | ||
770 | - } | 939 | + } |
940 | + }); | ||
941 | + } | ||
942 | + | ||
943 | + private ListenableFuture<TransportApiResponseMsg> handleGbtMedia( | ||
944 | + TransportProtos.Gbt28181MediaServerMsg requestMsg) { | ||
945 | + Optional<JsonNode> newMediaOpt = | ||
946 | + dataDecodingEncodingService.decode(requestMsg.getProfile().toByteArray()); | ||
947 | + newMediaOpt.ifPresent( | ||
948 | + json -> { | ||
949 | + MediaServerDTO entity = JacksonUtil.treeToValue(json, MediaServerDTO.class); | ||
950 | + MediaServerDTO queryEntity = | ||
951 | + mediaServerService.findMediaServerInfoById(null, entity.getMediaServerId()); | ||
952 | + if (null == queryEntity) { | ||
953 | + mediaServerService.saveMediaServer(entity); | ||
954 | + } else { | ||
955 | + entity.setId(queryEntity.getId()); | ||
956 | + mediaServerService.updateMediaServer(entity); | ||
957 | + } | ||
771 | }); | 958 | }); |
772 | 959 | ||
773 | - | 960 | + List<MediaServerDTO> allMediaKit = mediaServerService.getAllMediaKit(); |
961 | + Optional.ofNullable(allMediaKit) | ||
962 | + .ifPresent( | ||
963 | + all -> { | ||
964 | + all.forEach( | ||
965 | + dto -> { | ||
966 | + String key = dto.getMediaServerId(); | ||
967 | + ZLMediaKitServerConfig zlMediaKitServerConfig = connectZlmServer(dto); | ||
968 | + if (null != zlMediaKitServerConfig) { | ||
969 | + zlMediaKitServerConfig.setIp(dto.getIp()); | ||
970 | + zlMediaKitServerConfig.setHttpPort(dto.getHttpPort()); | ||
971 | + zlMediaKitServerConfig.setTenantId(dto.getTenantId()); | ||
972 | + // 进行上线操作 | ||
973 | + mediaServerNodeService.zlmServerOnline(zlMediaKitServerConfig); | ||
974 | + } else { | ||
975 | + mediaServerNodeService.zlmServerOffline(key); | ||
976 | + } | ||
977 | + }); | ||
978 | + }); | ||
979 | + TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder(); | ||
980 | + responseBuilder.addGbt28181MediaServerMsg(TransportProtos.Gbt28181MediaServerMsg.newBuilder()); | ||
981 | + return Futures.immediateFuture(responseBuilder.build()); | ||
982 | + } | ||
983 | + | ||
984 | + /** | ||
985 | + * 调用流媒体API接口获取流媒体配置 | ||
986 | + * | ||
987 | + * @param mediaServerItem | ||
988 | + * @return | ||
989 | + */ | ||
990 | + private ZLMediaKitServerConfig connectZlmServer(MediaServerDTO mediaServerItem) { | ||
991 | + log.info("启动流媒体【ZLMedia】验证,流媒体编号【{}】", mediaServerItem.getMediaServerId()); | ||
992 | + JsonNode responseJson = zlMediaKitRestFulUtils.getMediaServerConfig(mediaServerItem); | ||
993 | + if (responseJson == null) { | ||
994 | + log.error( | ||
995 | + "流媒体【{}】服务地址【{}:{}】无法访问", | ||
996 | + mediaServerItem.getMediaServerId(), | ||
997 | + mediaServerItem.getIp(), | ||
998 | + mediaServerItem.getHttpPort()); | ||
999 | + return null; | ||
1000 | + } | ||
1001 | + JsonNode data = responseJson.get(FastIotConstants.ZLMediaBody.DATA); | ||
1002 | + if (data != null && !data.isEmpty()) { | ||
1003 | + log.info( | ||
1004 | + "流媒体【{}:{}】调用成功,响应内容【{}】", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), data); | ||
1005 | + return org.thingsboard.server.common.data.yunteng.utils.JacksonUtil.convertValue( | ||
1006 | + data.get(0), ZLMediaKitServerConfig.class); | ||
1007 | + } else { | ||
1008 | + log.error( | ||
1009 | + "流媒体【{}:{}】调用失败,失败原因【{}】", | ||
1010 | + mediaServerItem.getIp(), | ||
1011 | + mediaServerItem.getHttpPort(), | ||
1012 | + responseJson.get(FastIotConstants.ZLMediaBody.MSG)); | ||
774 | } | 1013 | } |
1014 | + return null; | ||
1015 | + } | ||
775 | } | 1016 | } |
application/src/main/java/org/thingsboard/server/service/yunteng/media/ZLMediaKitStateRunner.java
deleted
100644 → 0
1 | -package org.thingsboard.server.service.yunteng.media; | ||
2 | - | ||
3 | -import com.fasterxml.jackson.databind.JsonNode; | ||
4 | -import lombok.Getter; | ||
5 | -import lombok.extern.slf4j.Slf4j; | ||
6 | -import org.springframework.beans.factory.annotation.Value; | ||
7 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
8 | -import org.springframework.stereotype.Component; | ||
9 | -import org.thingsboard.server.common.data.id.EntityId; | ||
10 | -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | ||
11 | -import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | ||
12 | -import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; | ||
13 | -import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; | ||
14 | -import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; | ||
15 | -import org.thingsboard.server.dao.util.yunteng.ZLMediaKitTaskUtils; | ||
16 | -import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerNodeService; | ||
17 | -import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService; | ||
18 | -import org.thingsboard.server.common.data.yunteng.config.media.MediaConfig; | ||
19 | -import org.thingsboard.server.queue.util.TbCoreComponent; | ||
20 | - | ||
21 | -import javax.annotation.PostConstruct; | ||
22 | -import java.util.List; | ||
23 | -import java.util.Map; | ||
24 | -import java.util.Optional; | ||
25 | - | ||
26 | -@Component("ZLMediaKitState") | ||
27 | -@TbCoreComponent | ||
28 | -@ConditionalOnExpression( | ||
29 | - "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
30 | -@Slf4j | ||
31 | -public class ZLMediaKitStateRunner { | ||
32 | - private final ZLMediaKitRestFulUtils zlMediaKitRestFulUtils; | ||
33 | - private final TkMediaServerNodeService tkMediaServerNodeService; | ||
34 | - private final TkMediaServerService tkMediaServerService; | ||
35 | - private final MediaConfig mediaConfig; | ||
36 | - private final ZLMediaKitTaskUtils zlMediaKitTaskUtils; | ||
37 | - private final Map<String, Boolean> startGetMedia; | ||
38 | - | ||
39 | - @Value("${media.defaultStateCheckIntervalInSec}") | ||
40 | - @Getter | ||
41 | - private int defaultStateCheckIntervalInSec; | ||
42 | - | ||
43 | - public ZLMediaKitStateRunner( | ||
44 | - ZLMediaKitRestFulUtils zlMediaKitRestFulUtils, | ||
45 | - TkMediaServerNodeService tkMediaServerNodeService, | ||
46 | - TkMediaServerService tkMediaServerService, | ||
47 | - MediaConfig mediaConfig, | ||
48 | - ZLMediaKitTaskUtils zlMediaKitTaskUtils, | ||
49 | - Map<String, Boolean> startGetMedia) { | ||
50 | - this.zlMediaKitRestFulUtils = zlMediaKitRestFulUtils; | ||
51 | - this.tkMediaServerNodeService = tkMediaServerNodeService; | ||
52 | - this.tkMediaServerService = tkMediaServerService; | ||
53 | - this.mediaConfig = mediaConfig; | ||
54 | - this.zlMediaKitTaskUtils = zlMediaKitTaskUtils; | ||
55 | - this.startGetMedia = startGetMedia; | ||
56 | - } | ||
57 | - | ||
58 | - @PostConstruct | ||
59 | - public void init() { | ||
60 | - updateDefaultMediaServer(); | ||
61 | - // 从数据库获取所有的流媒体信息 | ||
62 | - List<MediaServerDTO> dtoList = tkMediaServerService.getAllMediaKit(); | ||
63 | - | ||
64 | - Optional.ofNullable(dtoList).ifPresent( all ->{ | ||
65 | - all.forEach(dto ->{ | ||
66 | - String key = dto.getMediaServerId(); | ||
67 | - startGetMedia.put(key, true); | ||
68 | - zlMediaKitTaskUtils.startCronTask( | ||
69 | - key, | ||
70 | - () -> { | ||
71 | - ZLMediaKitServerConfig zlMediaKitServerConfig = getMediaServerConfig(dto); | ||
72 | - if (null != zlMediaKitServerConfig) { | ||
73 | - startGetMedia.remove(dto.getMediaServerId()); | ||
74 | - zlMediaKitTaskUtils.stop(key); | ||
75 | - zlMediaKitServerConfig.setIp(dto.getIp()); | ||
76 | - zlMediaKitServerConfig.setHttpPort(dto.getHttpPort()); | ||
77 | - zlMediaKitServerConfig.setTenantId(dto.getTenantId()); | ||
78 | - // 进行上线操作 | ||
79 | - tkMediaServerNodeService.zlmServerOnline(zlMediaKitServerConfig); | ||
80 | - } | ||
81 | - }, | ||
82 | - defaultStateCheckIntervalInSec); | ||
83 | - }); | ||
84 | - }); | ||
85 | - } | ||
86 | - | ||
87 | - private void updateDefaultMediaServer() { | ||
88 | - // 默认流媒体服务器 | ||
89 | - MediaServerDTO oldMediaServer = tkMediaServerService.findDefaultMediaServer(); | ||
90 | - MediaServerDTO defaultConfig = mediaConfig.getMediaSerItem(); | ||
91 | - if (oldMediaServer == null) { | ||
92 | - defaultConfig.setTenantId(EntityId.NULL_UUID.toString()); | ||
93 | - }else{ | ||
94 | - defaultConfig.setId(oldMediaServer.getId()); | ||
95 | - defaultConfig.setTenantId(oldMediaServer.getTenantId()); | ||
96 | - } | ||
97 | - tkMediaServerService.saveOrUpdateMediaServer(defaultConfig); | ||
98 | - } | ||
99 | - | ||
100 | - /** | ||
101 | - * 调用流媒体API接口获取流媒体配置 | ||
102 | - * @param mediaServerItem | ||
103 | - * @return | ||
104 | - */ | ||
105 | - private ZLMediaKitServerConfig getMediaServerConfig(MediaServerDTO mediaServerItem) { | ||
106 | - log.error("启动流媒体【ZLMedia】验证,流媒体编号【{}】",mediaServerItem.getMediaServerId()); | ||
107 | - if (startGetMedia == null) { | ||
108 | - return null; | ||
109 | - } | ||
110 | - if (!mediaServerItem.isDefaultServer() | ||
111 | - && tkMediaServerNodeService.getOne(mediaServerItem.getMediaServerId()).isEmpty()) { | ||
112 | - return null; | ||
113 | - } | ||
114 | - if (startGetMedia.get(mediaServerItem.getMediaServerId()) == null | ||
115 | - || !startGetMedia.get(mediaServerItem.getMediaServerId())) { | ||
116 | - return null; | ||
117 | - } | ||
118 | - JsonNode responseJson = zlMediaKitRestFulUtils.getMediaServerConfig(mediaServerItem); | ||
119 | - if(responseJson == null){ | ||
120 | - log.error("流媒体【{}】服务地址【{}:{}】无法访问",mediaServerItem.getMediaServerId(),mediaServerItem.getIp(),mediaServerItem.getHttpPort()); | ||
121 | - return null; | ||
122 | - } | ||
123 | - JsonNode data = responseJson.get(FastIotConstants.ZLMediaBody.DATA); | ||
124 | - if (data != null && !data.isEmpty()) { | ||
125 | - log.error("流媒体【{}:{}】调用成功,响应内容【{}】",mediaServerItem.getIp(),mediaServerItem.getHttpPort(),data); | ||
126 | - return JacksonUtil.convertValue(data.get(0), ZLMediaKitServerConfig.class); | ||
127 | - } | ||
128 | - log.error("流媒体【{}:{}】调用失败,失败原因【{}】",mediaServerItem.getIp(),mediaServerItem.getHttpPort(),responseJson.get(FastIotConstants.ZLMediaBody.MSG)); | ||
129 | - return null; | ||
130 | - } | ||
131 | -} |
@@ -721,6 +721,45 @@ transport: | @@ -721,6 +721,45 @@ transport: | ||
721 | gbt28181: | 721 | gbt28181: |
722 | # Enable/disable gbt28181 transport protocol. | 722 | # Enable/disable gbt28181 transport protocol. |
723 | enabled: "${GBT28181_ENABLED:false}" | 723 | enabled: "${GBT28181_ENABLED:false}" |
724 | + sip: | ||
725 | + # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡, | ||
726 | + # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 | ||
727 | + # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 | ||
728 | + # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 | ||
729 | + ip: ${GBT28181_SIP_IP:127.0.0.1} | ||
730 | + # [可选] 28181服务监听的端口 | ||
731 | + port: ${GBT28181_SIP_PORT:5060} | ||
732 | + #[可选] | ||
733 | + id: ${GBT28181_SIP_ID:51010700599000000001} | ||
734 | + # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) | ||
735 | + # 后两位为行业编码,定义参照附录D.3 | ||
736 | + # 3701020049标识山东济南历下区 信息行业接入 | ||
737 | + # [可选] | ||
738 | + domain: ${GBT28181_SIP_DOMAIN:5101070059} | ||
739 | + #[可选] | ||
740 | + password: ${GBT28181_SIP_PASSWORD:61332286} | ||
741 | + #zlm 默认服务器配置 | ||
742 | + media: | ||
743 | + id: ${GBT28181_MEDIA_GENERAL_ID:D2okJWKKaQ5bX7Va} | ||
744 | + # [必须修改] zlm服务器的内网IP | ||
745 | + ip: ${GBT28181_MEDIA_IP:127.0.0.1} | ||
746 | + # [必须修改] zlm服务器的http.port | ||
747 | + http-port: ${GBT28181_MEDIA_HTTP_PORT:28080} | ||
748 | + hook-ip: ${GBT28181_MEDIA_HOOK_IP:} | ||
749 | + stream-ip: ${GBT28181_MEDIA_STREAM_IP:} | ||
750 | + # [可选] zlm服务器的hook.admin_params=secret | ||
751 | + secret: ${GBT28181_MEDIA_API_SECRET:QhrTN7k6HcDnt0YyeolwHwiVYDgIHPMZ} | ||
752 | + # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 | ||
753 | + rtp: | ||
754 | + # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 | ||
755 | + enable: true | ||
756 | + # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 | ||
757 | + port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围 | ||
758 | + # [可选] 国标级联在此范围内选择端口发送媒体流, | ||
759 | + send-port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围 | ||
760 | + # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 | ||
761 | + record-assist-port: 0 | ||
762 | + defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:10}" | ||
724 | tcp: | 763 | tcp: |
725 | # Enable/disable tcp transport protocol. | 764 | # Enable/disable tcp transport protocol. |
726 | enabled: "${TCP_ENABLED:true}" | 765 | enabled: "${TCP_ENABLED:true}" |
@@ -1227,43 +1266,6 @@ logging: | @@ -1227,43 +1266,6 @@ logging: | ||
1227 | frp: | 1266 | frp: |
1228 | server: | 1267 | server: |
1229 | address: ${FRP_SERVER_ADDRESS:http://127.0.0.1} | 1268 | address: ${FRP_SERVER_ADDRESS:http://127.0.0.1} |
1230 | -sip: | ||
1231 | - # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡, | ||
1232 | - # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 | ||
1233 | - # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 | ||
1234 | - # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 | ||
1235 | - ip: ${GBT28181_SIP_IP:127.0.0.1} | ||
1236 | - # [可选] 28181服务监听的端口 | ||
1237 | - port: ${GBT28181_SIP_PORT:5060} | ||
1238 | - #[可选] | ||
1239 | - id: ${GBT28181_SIP_ID:51010700599000000001} | ||
1240 | - # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) | ||
1241 | - # 后两位为行业编码,定义参照附录D.3 | ||
1242 | - # 标识四川成都武侯下区 信息行业接入 | ||
1243 | - # [可选] | ||
1244 | - domain: ${GBT28181_SIP_DOMAIN:5101070059} | ||
1245 | - #[可选] | ||
1246 | - password: ${GBT28181_SIP_PASSWORD:61332286} | ||
1247 | -#zlm 默认服务器配置 | ||
1248 | -media: | ||
1249 | - id: ${GBT28181_MEDIA_GENERAL_ID:D2okJWKKaQ5bX7Va} | ||
1250 | - # [必须修改] zlm服务器的内网IP | ||
1251 | - ip: ${GBT28181_MEDIA_IP:127.0.0.1} | ||
1252 | - # [必须修改] zlm服务器的http.port | ||
1253 | - http-port: ${GBT28181_MEDIA_HTTP_PORT:28080} | ||
1254 | - # [可选] zlm服务器的hook.admin_params=secret | ||
1255 | - secret: ${GBT28181_MEDIA_API_SECRET:QhrTN7k6HcDnt0YyeolwHwiVYDgIHPMZ} | ||
1256 | - # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 | ||
1257 | - rtp: | ||
1258 | - # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 | ||
1259 | - enable: true | ||
1260 | - # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 | ||
1261 | - port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围 | ||
1262 | - # [可选] 国标级联在此范围内选择端口发送媒体流, | ||
1263 | - send-port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围 | ||
1264 | - # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 | ||
1265 | - record-assist-port: 0 | ||
1266 | - defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:10}" | ||
1267 | 1269 | ||
1268 | thingskit: | 1270 | thingskit: |
1269 | release: | 1271 | release: |
@@ -680,6 +680,7 @@ message TransportApiRequestMsg { | @@ -680,6 +680,7 @@ message TransportApiRequestMsg { | ||
680 | //Thingskit function | 680 | //Thingskit function |
681 | ScriptProto script = 14; | 681 | ScriptProto script = 14; |
682 | Gbt28181RequestMsg gbt28181RequestMsg = 15; | 682 | Gbt28181RequestMsg gbt28181RequestMsg = 15; |
683 | + Gbt28181MediaServerMsg gbt28181MediaServerMsg = 16; | ||
683 | } | 684 | } |
684 | 685 | ||
685 | /* Response from ThingsBoard Core Service to Transport Service */ | 686 | /* Response from ThingsBoard Core Service to Transport Service */ |
@@ -698,6 +699,7 @@ message TransportApiResponseMsg { | @@ -698,6 +699,7 @@ message TransportApiResponseMsg { | ||
698 | //Thingskit function | 699 | //Thingskit function |
699 | repeated ScriptProto scriptsResponseMsg = 11; | 700 | repeated ScriptProto scriptsResponseMsg = 11; |
700 | Gbt28181ResponseMsg gbt28181ResponseMsg = 12; | 701 | Gbt28181ResponseMsg gbt28181ResponseMsg = 12; |
702 | + repeated Gbt28181MediaServerMsg gbt28181MediaServerMsg = 13; | ||
701 | } | 703 | } |
702 | 704 | ||
703 | /* Messages that are handled by ThingsBoard Core Service */ | 705 | /* Messages that are handled by ThingsBoard Core Service */ |
@@ -826,5 +828,11 @@ message Gbt28181ResponseMsg{ | @@ -826,5 +828,11 @@ message Gbt28181ResponseMsg{ | ||
826 | int64 entityIdMSB = 11; | 828 | int64 entityIdMSB = 11; |
827 | int64 entityIdLSB = 12; | 829 | int64 entityIdLSB = 12; |
828 | } | 830 | } |
831 | +message Gbt28181MediaServerMsg{ | ||
832 | + bytes profile = 1; | ||
833 | +} | ||
834 | +message Gbt28181MediaResponseMsg{ | ||
835 | + repeated Gbt28181MediaServerMsg profiles = 1; | ||
836 | +} | ||
829 | 837 | ||
830 | 838 |
@@ -3,7 +3,6 @@ package org.thingsboard.server.common.data.yunteng.common.media; | @@ -3,7 +3,6 @@ package org.thingsboard.server.common.data.yunteng.common.media; | ||
3 | import java.util.*; | 3 | import java.util.*; |
4 | import lombok.extern.slf4j.Slf4j; | 4 | import lombok.extern.slf4j.Slf4j; |
5 | import org.springframework.beans.factory.annotation.Autowired; | 5 | import org.springframework.beans.factory.annotation.Autowired; |
6 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
7 | import org.springframework.stereotype.Component; | 6 | import org.springframework.stereotype.Component; |
8 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | 7 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
9 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 8 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
@@ -88,12 +87,14 @@ public class VideoStreamSessionManager { | @@ -88,12 +87,14 @@ public class VideoStreamSessionManager { | ||
88 | public Optional<SsrcTransactionDTO> getSsrcTransaction(String fullKey) { | 87 | public Optional<SsrcTransactionDTO> getSsrcTransaction(String fullKey) { |
89 | return cacheUtils.get(cacheName, fullKey); | 88 | return cacheUtils.get(cacheName, fullKey); |
90 | } | 89 | } |
91 | - public Optional<SsrcTransactionDTO> getSsrcTransaction(String cameraCode, String channelId, String stream) { | ||
92 | - Optional<Set<String>> keys =getSsrcTransactionChannelKey(cameraCode, channelId,stream); | ||
93 | 90 | ||
94 | - if(keys.isPresent()){ | ||
95 | - Optional<String> fullKey =keys.get().stream().findFirst(); | ||
96 | - if(fullKey.isPresent()){ | 91 | + public Optional<SsrcTransactionDTO> getSsrcTransaction( |
92 | + String cameraCode, String channelId, String stream) { | ||
93 | + Optional<Set<String>> keys = getSsrcTransactionChannelKey(cameraCode, channelId, stream); | ||
94 | + | ||
95 | + if (keys.isPresent()) { | ||
96 | + Optional<String> fullKey = keys.get().stream().findFirst(); | ||
97 | + if (fullKey.isPresent()) { | ||
97 | return getSsrcTransaction(fullKey.get()); | 98 | return getSsrcTransaction(fullKey.get()); |
98 | } | 99 | } |
99 | } | 100 | } |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/config/media/MediaConfig.java
deleted
100644 → 0
1 | -package org.thingsboard.server.common.data.yunteng.config.media; | ||
2 | - | ||
3 | -import lombok.Data; | ||
4 | -import lombok.extern.slf4j.Slf4j; | ||
5 | -import org.springframework.beans.factory.annotation.Value; | ||
6 | -import org.springframework.boot.context.properties.ConfigurationProperties; | ||
7 | -import org.springframework.stereotype.Component; | ||
8 | -import org.springframework.util.ObjectUtils; | ||
9 | -import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; | ||
10 | - | ||
11 | -import java.net.InetAddress; | ||
12 | -import java.net.UnknownHostException; | ||
13 | -import java.util.Objects; | ||
14 | -import java.util.regex.Pattern; | ||
15 | - | ||
16 | -/** | ||
17 | - * 配置文件里面的流媒体配置信息 | ||
18 | - */ | ||
19 | -@ConfigurationProperties(prefix = "media") | ||
20 | -@Component | ||
21 | -@Data | ||
22 | -@Slf4j | ||
23 | -public class MediaConfig { | ||
24 | - @Value("${media.id}") | ||
25 | - private String mediaServerId; | ||
26 | - | ||
27 | - @Value("${media.ip}") | ||
28 | - private String ip; | ||
29 | - | ||
30 | - @Value("${media.hook-ip:}") | ||
31 | - private String hookIp; | ||
32 | - | ||
33 | - @Value("${sip.ip}") | ||
34 | - private String sipIp; | ||
35 | - | ||
36 | - @Value("${sip.domain}") | ||
37 | - private String sipDomain; | ||
38 | - | ||
39 | - @Value("${media.sdp-ip:${media.ip}}") | ||
40 | - private String sdpIp; | ||
41 | - | ||
42 | - @Value("${media.stream-ip:${media.ip}}") | ||
43 | - private String streamIp; | ||
44 | - | ||
45 | - @Value("${media.http-port}") | ||
46 | - private Integer httpPort; | ||
47 | - | ||
48 | - @Value("${media.http-ssl-port:0}") | ||
49 | - private Integer httpSslPort = 0; | ||
50 | - | ||
51 | - @Value("${media.rtmp-port:0}") | ||
52 | - private Integer rtmpPort = 0; | ||
53 | - | ||
54 | - @Value("${media.rtmp-ssl-port:0}") | ||
55 | - private Integer rtmpSslPort = 0; | ||
56 | - | ||
57 | - @Value("${media.rtp-proxy-port:0}") | ||
58 | - private Integer rtpProxyPort = 0; | ||
59 | - | ||
60 | - @Value("${media.rtsp-port:0}") | ||
61 | - private Integer rtspPort = 0; | ||
62 | - | ||
63 | - @Value("${media.rtsp-ssl-port:0}") | ||
64 | - private Integer rtspSslPort = 0; | ||
65 | - | ||
66 | - @Value("${media.auto-config:true}") | ||
67 | - private boolean autoConfig = true; | ||
68 | - | ||
69 | - @Value("${media.secret}") | ||
70 | - private String secret; | ||
71 | - | ||
72 | - @Value("${media.rtp.enable}") | ||
73 | - private boolean rtpEnable; | ||
74 | - | ||
75 | - @Value("${media.rtp.port-range}") | ||
76 | - private String rtpPortRange; | ||
77 | - | ||
78 | - @Value("${media.rtp.send-port-range}") | ||
79 | - private String rtpSendPortRange; | ||
80 | - | ||
81 | - @Value("${media.record-assist-port:0}") | ||
82 | - private Integer recordAssistPort = 0; | ||
83 | - private boolean status; | ||
84 | - | ||
85 | - public MediaServerDTO getMediaSerItem() { | ||
86 | - MediaServerDTO mediaServerItem = new MediaServerDTO(); | ||
87 | - mediaServerItem.setMediaServerId(mediaServerId); | ||
88 | - mediaServerItem.setIp(ip); | ||
89 | - mediaServerItem.setDefaultServer(true); | ||
90 | - mediaServerItem.setHookIp(getHookIp()); | ||
91 | - mediaServerItem.setSdpIp(getSdpIp()); | ||
92 | - mediaServerItem.setStreamIp(getStreamIp()); | ||
93 | - mediaServerItem.setHttpPort(httpPort); | ||
94 | - mediaServerItem.setHttpSslPort(httpSslPort); | ||
95 | - mediaServerItem.setRtmpPort(rtmpPort); | ||
96 | - mediaServerItem.setRtmpSslPort(rtmpSslPort); | ||
97 | - mediaServerItem.setRtpProxyPort(getRtpProxyPort()); | ||
98 | - mediaServerItem.setRtspPort(rtspPort); | ||
99 | - mediaServerItem.setRtspSslPort(rtspSslPort); | ||
100 | - mediaServerItem.setAutoConfig(autoConfig); | ||
101 | - mediaServerItem.setSecret(secret); | ||
102 | - mediaServerItem.setRtpEnable(rtpEnable); | ||
103 | - mediaServerItem.setRtpPortRange(rtpPortRange); | ||
104 | - mediaServerItem.setSendRtpPortRange(rtpSendPortRange); | ||
105 | - mediaServerItem.setRecordAssistPort(recordAssistPort); | ||
106 | - mediaServerItem.setHookAliveInterval(30.00f); | ||
107 | - mediaServerItem.setStatus(status); | ||
108 | - return mediaServerItem; | ||
109 | - } | ||
110 | - | ||
111 | - public String getHookIp() { | ||
112 | - if (ObjectUtils.isEmpty(hookIp)) { | ||
113 | - return sipIp.split(",")[0]; | ||
114 | - } else { | ||
115 | - return hookIp; | ||
116 | - } | ||
117 | - } | ||
118 | - | ||
119 | - public String getSipIp() { | ||
120 | - if (sipIp == null) { | ||
121 | - return this.ip; | ||
122 | - } else { | ||
123 | - return sipIp; | ||
124 | - } | ||
125 | - } | ||
126 | - | ||
127 | - public int getRtpProxyPort() { | ||
128 | - return Objects.requireNonNullElse(rtpProxyPort, 0); | ||
129 | - } | ||
130 | - | ||
131 | - public String getSdpIp() { | ||
132 | - if (ObjectUtils.isEmpty(sdpIp)) { | ||
133 | - return ip; | ||
134 | - } else { | ||
135 | - if (isValidIPAddress(sdpIp)) { | ||
136 | - return sdpIp; | ||
137 | - } else { | ||
138 | - // 按照域名解析 | ||
139 | - String hostAddress = null; | ||
140 | - try { | ||
141 | - hostAddress = InetAddress.getByName(sdpIp).getHostAddress(); | ||
142 | - } catch (UnknownHostException e) { | ||
143 | - log.error("[获取SDP IP]: 域名解析失败"); | ||
144 | - } | ||
145 | - return hostAddress; | ||
146 | - } | ||
147 | - } | ||
148 | - } | ||
149 | - | ||
150 | - public String getStreamIp() { | ||
151 | - if (ObjectUtils.isEmpty(streamIp)) { | ||
152 | - return ip; | ||
153 | - } else { | ||
154 | - return streamIp; | ||
155 | - } | ||
156 | - } | ||
157 | - | ||
158 | - private boolean isValidIPAddress(String ipAddress) { | ||
159 | - if ((ipAddress != null) && (!ipAddress.isEmpty())) { | ||
160 | - return Pattern.matches( | ||
161 | - "^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", | ||
162 | - ipAddress); | ||
163 | - } | ||
164 | - return false; | ||
165 | - } | ||
166 | -} |
1 | package org.thingsboard.server.common.data.yunteng.config.media; | 1 | package org.thingsboard.server.common.data.yunteng.config.media; |
2 | 2 | ||
3 | import lombok.Data; | 3 | import lombok.Data; |
4 | -import org.springframework.boot.context.properties.ConfigurationProperties; | ||
5 | import org.springframework.stereotype.Component; | 4 | import org.springframework.stereotype.Component; |
6 | 5 | ||
7 | -@ConfigurationProperties(prefix = "user-settings") | ||
8 | @Component | 6 | @Component |
9 | @Data | 7 | @Data |
10 | public class UserSetting { | 8 | public class UserSetting { |
11 | - private String serverId = "000000"; | ||
12 | - private Boolean seniorSdp = Boolean.FALSE; | ||
13 | - private Boolean pushAuthority = Boolean.TRUE; | ||
14 | - private Boolean recordSip = Boolean.TRUE; | ||
15 | - private Boolean recordPushLive = Boolean.TRUE; | ||
16 | - private String recordPath = null; | ||
17 | - private Boolean streamOnDemand = Boolean.TRUE; | ||
18 | - private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE; | ||
19 | - private Integer playTimeout = 30000; | 9 | + private String serverId = "000000"; |
10 | + private Boolean seniorSdp = Boolean.FALSE; | ||
11 | + private Boolean pushAuthority = Boolean.TRUE; | ||
12 | + private Boolean recordSip = Boolean.TRUE; | ||
13 | + private Boolean recordPushLive = Boolean.TRUE; | ||
14 | + private String recordPath = null; | ||
15 | + private Boolean streamOnDemand = Boolean.TRUE; | ||
16 | + private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE; | ||
17 | + private Integer playTimeout = 30000; | ||
20 | } | 18 | } |
@@ -3,8 +3,6 @@ package org.thingsboard.server.common.data.yunteng.dto.sip; | @@ -3,8 +3,6 @@ package org.thingsboard.server.common.data.yunteng.dto.sip; | ||
3 | import io.swagger.annotations.ApiModelProperty; | 3 | import io.swagger.annotations.ApiModelProperty; |
4 | import lombok.Data; | 4 | import lombok.Data; |
5 | import lombok.EqualsAndHashCode; | 5 | import lombok.EqualsAndHashCode; |
6 | -import org.springframework.util.ObjectUtils; | ||
7 | -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | ||
8 | import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; | 6 | import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; |
9 | 7 | ||
10 | @EqualsAndHashCode(callSuper = true) | 8 | @EqualsAndHashCode(callSuper = true) |
@@ -63,11 +61,11 @@ public class MediaServerDTO extends TenantDTO { | @@ -63,11 +61,11 @@ public class MediaServerDTO extends TenantDTO { | ||
63 | @ApiModelProperty(value = "流媒体服务器的状态") | 61 | @ApiModelProperty(value = "流媒体服务器的状态") |
64 | private boolean status; | 62 | private boolean status; |
65 | 63 | ||
66 | - @ApiModelProperty(value = "多端口RTP收流端口范围") | 64 | + @ApiModelProperty(value = "RTP收流端口范围") |
67 | private String rtpPortRange; | 65 | private String rtpPortRange; |
68 | 66 | ||
69 | - @ApiModelProperty(value = "RTP发流端口范围") | ||
70 | - private String sendRtpPortRange; | 67 | + @ApiModelProperty(value = "RTP推流端口范围") |
68 | + private String rtpSendPortRange; | ||
71 | 69 | ||
72 | @ApiModelProperty(value = "assist服务端口") | 70 | @ApiModelProperty(value = "assist服务端口") |
73 | private Integer recordAssistPort; | 71 | private Integer recordAssistPort; |
@@ -81,33 +79,7 @@ public class MediaServerDTO extends TenantDTO { | @@ -81,33 +79,7 @@ public class MediaServerDTO extends TenantDTO { | ||
81 | @ApiModelProperty(value = "当前使用到的端口") | 79 | @ApiModelProperty(value = "当前使用到的端口") |
82 | private Integer currentPort; | 80 | private Integer currentPort; |
83 | 81 | ||
84 | - public MediaServerDTO(){ | ||
85 | - | ||
86 | - } | ||
87 | - public MediaServerDTO(ZLMediaKitServerConfig zlmServerConfig, String sipIp) { | ||
88 | - setId(zlmServerConfig.getGeneralMediaServerId()); | ||
89 | - ip = zlmServerConfig.getIp(); | ||
90 | - hookIp = ObjectUtils.isEmpty(zlmServerConfig.getHookIp()) ? sipIp : zlmServerConfig.getHookIp(); | ||
91 | - sdpIp = | ||
92 | - ObjectUtils.isEmpty(zlmServerConfig.getSdpIp()) | ||
93 | - ? zlmServerConfig.getIp() | ||
94 | - : zlmServerConfig.getSdpIp(); | ||
95 | - streamIp = | ||
96 | - ObjectUtils.isEmpty(zlmServerConfig.getStreamIp()) | ||
97 | - ? zlmServerConfig.getIp() | ||
98 | - : zlmServerConfig.getStreamIp(); | ||
99 | - httpPort = zlmServerConfig.getHttpPort(); | ||
100 | - httpSslPort = zlmServerConfig.getHttpSslPort(); | ||
101 | - rtmpPort = zlmServerConfig.getRtmpPort(); | ||
102 | - rtmpSslPort = zlmServerConfig.getRtmpSslPort(); | ||
103 | - rtpProxyPort = zlmServerConfig.getRtpProxyPort(); | ||
104 | - rtspPort = zlmServerConfig.getRtspPort(); | ||
105 | - rtspSslPort = zlmServerConfig.getRtspSslPort(); | ||
106 | - autoConfig = true; // 默认值true; | ||
107 | - secret = zlmServerConfig.getApiSecret(); | ||
108 | - hookAliveInterval = zlmServerConfig.getHookAliveInterval(); | ||
109 | - rtpEnable = false; // 默认使用单端口;直到用户自己设置开启多端口 | ||
110 | - rtpPortRange = zlmServerConfig.getPortRange().replace("_", ","); // 默认使用30000,30500作为级联时发送流的端口号 | ||
111 | - recordAssistPort = 0; // 默认关闭 | ||
112 | - } | 82 | + private String hookEnable; |
83 | + | ||
84 | + public MediaServerDTO() {} | ||
113 | } | 85 | } |
1 | package org.thingsboard.server.common.data.yunteng.dto.sip; | 1 | package org.thingsboard.server.common.data.yunteng.dto.sip; |
2 | 2 | ||
3 | import io.swagger.annotations.ApiModelProperty; | 3 | import io.swagger.annotations.ApiModelProperty; |
4 | +import java.io.Serializable; | ||
4 | import lombok.Data; | 5 | import lombok.Data; |
5 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 6 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
6 | 7 | ||
7 | -import java.io.Serializable; | ||
8 | - | ||
9 | @Data | 8 | @Data |
10 | public class SipDeviceDTO implements Serializable { | 9 | public class SipDeviceDTO implements Serializable { |
11 | @ApiModelProperty(value = "设备国标编号") | 10 | @ApiModelProperty(value = "设备国标编号") |
@@ -37,6 +36,7 @@ public class SipDeviceDTO implements Serializable { | @@ -37,6 +36,7 @@ public class SipDeviceDTO implements Serializable { | ||
37 | 36 | ||
38 | @ApiModelProperty(value = "是否开启ssrc校验,默认关闭,开启可以防止串流") | 37 | @ApiModelProperty(value = "是否开启ssrc校验,默认关闭,开启可以防止串流") |
39 | private boolean ssrcCheck = true; | 38 | private boolean ssrcCheck = true; |
39 | + | ||
40 | @ApiModelProperty(value = "生产厂商") | 40 | @ApiModelProperty(value = "生产厂商") |
41 | private String manufacturer; | 41 | private String manufacturer; |
42 | 42 | ||
@@ -48,12 +48,13 @@ public class SipDeviceDTO implements Serializable { | @@ -48,12 +48,13 @@ public class SipDeviceDTO implements Serializable { | ||
48 | 48 | ||
49 | @ApiModelProperty(value = "固件版本") | 49 | @ApiModelProperty(value = "固件版本") |
50 | private String firmware; | 50 | private String firmware; |
51 | + | ||
51 | public Integer getStreamModeForParam() { | 52 | public Integer getStreamModeForParam() { |
52 | if (FastIotConstants.StreamMode.UDP.equalsIgnoreCase(streamMode)) { | 53 | if (FastIotConstants.StreamMode.UDP.equalsIgnoreCase(streamMode)) { |
53 | return 0; | 54 | return 0; |
54 | - }else if (FastIotConstants.StreamMode.TCP_PASSIVE.equalsIgnoreCase(streamMode)) { | 55 | + } else if (FastIotConstants.StreamMode.TCP_PASSIVE.equalsIgnoreCase(streamMode)) { |
55 | return 1; | 56 | return 1; |
56 | - }else if (FastIotConstants.StreamMode.TCP_ACTIVE.equalsIgnoreCase(streamMode)) { | 57 | + } else if (FastIotConstants.StreamMode.TCP_ACTIVE.equalsIgnoreCase(streamMode)) { |
57 | return 2; | 58 | return 2; |
58 | } | 59 | } |
59 | return 0; | 60 | return 0; |
@@ -2,6 +2,8 @@ package org.thingsboard.server.common.data.yunteng.utils; | @@ -2,6 +2,8 @@ package org.thingsboard.server.common.data.yunteng.utils; | ||
2 | 2 | ||
3 | import lombok.extern.slf4j.Slf4j; | 3 | import lombok.extern.slf4j.Slf4j; |
4 | 4 | ||
5 | +import java.util.regex.Pattern; | ||
6 | + | ||
5 | /** | 7 | /** |
6 | * 数值格式相关工具类 | 8 | * 数值格式相关工具类 |
7 | */ | 9 | */ |
@@ -35,4 +37,18 @@ public class DataUtils { | @@ -35,4 +37,18 @@ public class DataUtils { | ||
35 | return false; | 37 | return false; |
36 | } | 38 | } |
37 | } | 39 | } |
40 | + | ||
41 | + /** | ||
42 | + * 是否有效的IP地址 | ||
43 | + * @param ipAddress IP地址字符串 | ||
44 | + * @return | ||
45 | + */ | ||
46 | + public static boolean isIPAddress(String ipAddress) { | ||
47 | + if ((ipAddress != null) && (!ipAddress.isEmpty())) { | ||
48 | + return Pattern.matches( | ||
49 | + "^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", | ||
50 | + ipAddress); | ||
51 | + } | ||
52 | + return false; | ||
53 | + } | ||
38 | } | 54 | } |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/adaptors/GbtTransportAdaptor.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2022 The Thingsboard Authors | ||
3 | - * <p> | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * <p> | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * <p> | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.transport.adaptors; | ||
17 | - | ||
18 | -import io.netty.buffer.ByteBuf; | ||
19 | -import io.netty.handler.codec.mqtt.MqttPublishMessage; | ||
20 | -import java.nio.charset.Charset; | ||
21 | -import java.nio.charset.StandardCharsets; | ||
22 | -import java.util.Optional; | ||
23 | -import java.util.concurrent.ExecutionException; | ||
24 | -import org.thingsboard.server.common.data.ota.OtaPackageType; | ||
25 | -import org.thingsboard.server.common.transport.adaptor.AdaptorException; | ||
26 | -import org.thingsboard.server.gen.transport.TransportProtos.*; | ||
27 | -import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; | ||
28 | - | ||
29 | -/** | ||
30 | - * 将收到的数据流转换为接口需要的数据格式 | ||
31 | - * 1、基于解析脚本将ByteBuf转JSON对象。 | ||
32 | - * 2、将JSON对象转PROTOBUF对象。 | ||
33 | - */ | ||
34 | -public interface GbtTransportAdaptor { | ||
35 | - static char[] HEX_VOCABLE = {'0', '1', '2', '3', '4', '5', '6', '7', | ||
36 | - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | ||
37 | - static final Charset UTF8 = StandardCharsets.UTF_8; | ||
38 | - | ||
39 | - | ||
40 | - /** | ||
41 | - * 设备数据转遥测数据 | ||
42 | - * | ||
43 | - * @param ctx | ||
44 | - * @param inbound 设备上报的数据字符串 | ||
45 | - * @return 平台需要的遥测数据 | ||
46 | - * @throws AdaptorException | ||
47 | - */ | ||
48 | - PostTelemetryMsg convertToPostTelemetry(GbtDeviceSessionCtx ctx, String inbound) throws AdaptorException; | ||
49 | - | ||
50 | - | ||
51 | - PostAttributeMsg convertToPostAttributes(GbtDeviceSessionCtx ctx, String inbound) throws AdaptorException; | ||
52 | - | ||
53 | - GetAttributeRequestMsg convertToGetAttributes(GbtDeviceSessionCtx ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException; | ||
54 | - | ||
55 | - ToDeviceRpcResponseMsg convertToDeviceRpcResponse(GbtDeviceSessionCtx ctx, String inbound) throws AdaptorException; | ||
56 | - | ||
57 | - ToServerRpcRequestMsg convertToServerRpcRequest(GbtDeviceSessionCtx ctx, MqttPublishMessage mqttMsg, String topicBase) throws AdaptorException; | ||
58 | - | ||
59 | - | ||
60 | - | ||
61 | - Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException; | ||
62 | - | ||
63 | - | ||
64 | - Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, AttributeUpdateNotificationMsg notificationMsg, String topic) throws AdaptorException; | ||
65 | - | ||
66 | - | ||
67 | - Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, ToDeviceRpcRequestMsg rpcRequest) throws ExecutionException, InterruptedException; | ||
68 | - | ||
69 | - Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, ToServerRpcResponseMsg rpcResponse, String topicBase) throws AdaptorException; | ||
70 | - | ||
71 | - ProvisionDeviceRequestMsg convertToProvisionRequestMsg(GbtDeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException; | ||
72 | - | ||
73 | - Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException; | ||
74 | - | ||
75 | - Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException; | ||
76 | - | ||
77 | - public static byte[] toBytes(ByteBuf inbound) { | ||
78 | - byte[] bytes = new byte[inbound.readableBytes()]; | ||
79 | - int readerIndex = inbound.readerIndex(); | ||
80 | - inbound.getBytes(readerIndex, bytes); | ||
81 | - return bytes; | ||
82 | - } | ||
83 | - | ||
84 | - public static String bytesToHex(byte[] bs) { | ||
85 | - StringBuilder sb = new StringBuilder(); | ||
86 | - for (byte b : bs) { | ||
87 | - int high = (b >> 4) & 0x0f; | ||
88 | - int low = b & 0x0f; | ||
89 | - sb.append(HEX_VOCABLE[high]); | ||
90 | - sb.append(HEX_VOCABLE[low]); | ||
91 | - } | ||
92 | - return sb.toString(); | ||
93 | - } | ||
94 | -} |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/adaptors/JsonGbtAdaptor.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2022 The Thingsboard Authors | ||
3 | - * <p> | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * <p> | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * <p> | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.transport.adaptors; | ||
17 | - | ||
18 | -import com.google.gson.JsonElement; | ||
19 | -import com.google.gson.JsonObject; | ||
20 | -import com.google.gson.JsonParser; | ||
21 | -import com.google.gson.JsonSyntaxException; | ||
22 | -import io.netty.buffer.ByteBuf; | ||
23 | -import io.netty.handler.codec.mqtt.MqttPublishMessage; | ||
24 | -import java.nio.charset.Charset; | ||
25 | -import java.nio.charset.StandardCharsets; | ||
26 | -import java.util.*; | ||
27 | -import java.util.concurrent.ExecutionException; | ||
28 | -import lombok.extern.slf4j.Slf4j; | ||
29 | -import org.springframework.stereotype.Component; | ||
30 | -import org.springframework.util.StringUtils; | ||
31 | -import org.thingsboard.server.common.data.ota.OtaPackageType; | ||
32 | -import org.thingsboard.server.common.transport.adaptor.AdaptorException; | ||
33 | -import org.thingsboard.server.common.transport.adaptor.JsonConverter; | ||
34 | -import org.thingsboard.server.gen.transport.TransportProtos; | ||
35 | -import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; | ||
36 | - | ||
37 | -/** | ||
38 | - * @author Andrew Shvayka | ||
39 | - */ | ||
40 | -@Component | ||
41 | -@Slf4j | ||
42 | -public class JsonGbtAdaptor implements GbtTransportAdaptor { | ||
43 | - | ||
44 | - protected static final Charset UTF8 = StandardCharsets.UTF_8; | ||
45 | - private static final JsonParser parser = new JsonParser(); | ||
46 | - | ||
47 | - | ||
48 | - @Override | ||
49 | - public TransportProtos.PostTelemetryMsg convertToPostTelemetry(GbtDeviceSessionCtx ctx, String payload) throws AdaptorException { | ||
50 | - try { | ||
51 | - return JsonConverter.convertToTelemetryProto(new JsonParser().parse(payload)); | ||
52 | - } catch (IllegalStateException | JsonSyntaxException ex) { | ||
53 | - log.debug("Failed to decode post telemetry request", ex); | ||
54 | - throw new AdaptorException(ex); | ||
55 | - } | ||
56 | - } | ||
57 | - | ||
58 | - | ||
59 | - @Override | ||
60 | - public TransportProtos.PostAttributeMsg convertToPostAttributes(GbtDeviceSessionCtx ctx, String payload) throws AdaptorException { | ||
61 | - try { | ||
62 | - return JsonConverter.convertToAttributesProto(new JsonParser().parse(payload)); | ||
63 | - } catch (IllegalStateException | JsonSyntaxException ex) { | ||
64 | - log.debug("Failed to decode post attributes request", ex); | ||
65 | - throw new AdaptorException(ex); | ||
66 | - } | ||
67 | - } | ||
68 | - | ||
69 | - | ||
70 | - @Override | ||
71 | - public TransportProtos.ProvisionDeviceRequestMsg convertToProvisionRequestMsg(GbtDeviceSessionCtx ctx, MqttPublishMessage inbound) throws AdaptorException { | ||
72 | - String payload = validatePayload(ctx.getSessionId(), inbound.payload(), false); | ||
73 | - try { | ||
74 | - return JsonConverter.convertToProvisionRequestMsg(payload); | ||
75 | - } catch (IllegalStateException | JsonSyntaxException ex) { | ||
76 | - throw new AdaptorException(ex); | ||
77 | - } | ||
78 | - } | ||
79 | - | ||
80 | - @Override | ||
81 | - public TransportProtos.GetAttributeRequestMsg convertToGetAttributes(GbtDeviceSessionCtx ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException { | ||
82 | - return processGetAttributeRequestMsg(inbound, topicBase); | ||
83 | - } | ||
84 | - | ||
85 | - @Override | ||
86 | - public TransportProtos.ToDeviceRpcResponseMsg convertToDeviceRpcResponse(GbtDeviceSessionCtx ctx, String inbound) throws AdaptorException { | ||
87 | - try { | ||
88 | -// Integer requestId = ctx.getRpcRequesting(inbound.getIdentifier()); | ||
89 | -// if(requestId != null){ | ||
90 | -// String payload = JacksonUtil.toString(inbound.getDatas()); | ||
91 | -// return TransportProtos.ToDeviceRpcResponseMsg.newBuilder().setRequestId(requestId).setPayload(payload).build(); | ||
92 | -// } | ||
93 | - return null; | ||
94 | - } catch (RuntimeException e) { | ||
95 | - log.debug("Failed to decode rpc response", e); | ||
96 | - throw new AdaptorException(e); | ||
97 | - } | ||
98 | - } | ||
99 | - | ||
100 | - @Override | ||
101 | - public TransportProtos.ToServerRpcRequestMsg convertToServerRpcRequest(GbtDeviceSessionCtx ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException { | ||
102 | - return processToServerRpcRequestMsg(ctx, inbound, topicBase); | ||
103 | - } | ||
104 | - | ||
105 | - @Override | ||
106 | - public Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException { | ||
107 | - return processConvertFromAttributeResponseMsg(ctx, responseMsg, topicBase); | ||
108 | - } | ||
109 | - | ||
110 | - | ||
111 | - @Override | ||
112 | - public Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, TransportProtos.AttributeUpdateNotificationMsg notificationMsg, String topic) { | ||
113 | - return Optional.of(createTcpMessage(ctx, JsonConverter.toJson(notificationMsg))); | ||
114 | - } | ||
115 | - | ||
116 | - | ||
117 | - @Override | ||
118 | - public Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, TransportProtos.ToDeviceRpcRequestMsg rpcRequest) throws ExecutionException, InterruptedException { | ||
119 | - String payload = rpcRequest.getParams();//methodThingskit | ||
120 | - | ||
121 | -// TcpDownEntry data = new TcpDownEntry(); | ||
122 | -// data.setDatas(payload); | ||
123 | -// data.setIdentifier(payload); | ||
124 | - return Optional.of("data"); | ||
125 | - } | ||
126 | - | ||
127 | - | ||
128 | - | ||
129 | - @Override | ||
130 | - public Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, TransportProtos.ToServerRpcResponseMsg rpcResponse, String topicBase) { | ||
131 | - return Optional.of(createTcpMessage(ctx, JsonConverter.toJson(rpcResponse))); | ||
132 | - } | ||
133 | - | ||
134 | - @Override | ||
135 | - public Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, TransportProtos.ProvisionDeviceResponseMsg provisionResponse) { | ||
136 | - return Optional.of(createTcpMessage(ctx, JsonConverter.toJson(provisionResponse))); | ||
137 | - } | ||
138 | - | ||
139 | - @Override | ||
140 | - public Optional<String> convertToPublish(GbtDeviceSessionCtx ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) { | ||
141 | - return Optional.of(null); | ||
142 | - } | ||
143 | - | ||
144 | - public static JsonElement validateJsonPayload(UUID sessionId, ByteBuf payloadData) throws AdaptorException { | ||
145 | - String payload = validatePayload(sessionId, payloadData, false); | ||
146 | - try { | ||
147 | - return new JsonParser().parse(payload); | ||
148 | - } catch (JsonSyntaxException ex) { | ||
149 | - log.debug("Payload is in incorrect format: {}", payload); | ||
150 | - throw new AdaptorException(ex); | ||
151 | - } | ||
152 | - } | ||
153 | - | ||
154 | - private TransportProtos.GetAttributeRequestMsg processGetAttributeRequestMsg(MqttPublishMessage inbound, String topicBase) throws AdaptorException { | ||
155 | - String topicName = inbound.variableHeader().topicName(); | ||
156 | - try { | ||
157 | - TransportProtos.GetAttributeRequestMsg.Builder result = TransportProtos.GetAttributeRequestMsg.newBuilder(); | ||
158 | - result.setRequestId(getRequestId(topicName, topicBase)); | ||
159 | - String payload = inbound.payload().toString(UTF8); | ||
160 | - JsonElement requestBody = new JsonParser().parse(payload); | ||
161 | - Set<String> clientKeys = toStringSet(requestBody, "clientKeys"); | ||
162 | - Set<String> sharedKeys = toStringSet(requestBody, "sharedKeys"); | ||
163 | - if (clientKeys != null) { | ||
164 | - result.addAllClientAttributeNames(clientKeys); | ||
165 | - } | ||
166 | - if (sharedKeys != null) { | ||
167 | - result.addAllSharedAttributeNames(sharedKeys); | ||
168 | - } | ||
169 | - return result.build(); | ||
170 | - } catch (RuntimeException e) { | ||
171 | - log.debug("Failed to decode get attributes request", e); | ||
172 | - throw new AdaptorException(e); | ||
173 | - } | ||
174 | - } | ||
175 | - | ||
176 | - | ||
177 | - private TransportProtos.ToServerRpcRequestMsg processToServerRpcRequestMsg(GbtDeviceSessionCtx ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException { | ||
178 | - String topicName = inbound.variableHeader().topicName(); | ||
179 | - String payload = validatePayload(ctx.getSessionId(), inbound.payload(), false); | ||
180 | - try { | ||
181 | - int requestId = getRequestId(topicName, topicBase); | ||
182 | - return JsonConverter.convertToServerRpcRequest(new JsonParser().parse(payload), requestId); | ||
183 | - } catch (IllegalStateException | JsonSyntaxException ex) { | ||
184 | - log.debug("Failed to decode to server rpc request", ex); | ||
185 | - throw new AdaptorException(ex); | ||
186 | - } | ||
187 | - } | ||
188 | - | ||
189 | - private Optional<String> processConvertFromAttributeResponseMsg(GbtDeviceSessionCtx ctx, TransportProtos.GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException { | ||
190 | - if (!StringUtils.isEmpty(responseMsg.getError())) { | ||
191 | - throw new AdaptorException(responseMsg.getError()); | ||
192 | - } else { | ||
193 | - int requestId = responseMsg.getRequestId(); | ||
194 | - if (requestId >= 0) { | ||
195 | - return Optional.of(createTcpMessage(ctx, | ||
196 | - JsonConverter.toJson(responseMsg))); | ||
197 | - } | ||
198 | - return Optional.empty(); | ||
199 | - } | ||
200 | - } | ||
201 | - | ||
202 | - private Optional<String> processConvertFromGatewayAttributeResponseMsg(GbtDeviceSessionCtx ctx, String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) throws AdaptorException { | ||
203 | - if (!StringUtils.isEmpty(responseMsg.getError())) { | ||
204 | - throw new AdaptorException(responseMsg.getError()); | ||
205 | - } else { | ||
206 | - JsonObject result = JsonConverter.getJsonObjectForGateway(deviceName, responseMsg); | ||
207 | - return Optional.of(createTcpMessage(ctx, result)); | ||
208 | - } | ||
209 | - } | ||
210 | - | ||
211 | - | ||
212 | - private Set<String> toStringSet(JsonElement requestBody, String name) { | ||
213 | - JsonElement element = requestBody.getAsJsonObject().get(name); | ||
214 | - if (element != null) { | ||
215 | - return new HashSet<>(Arrays.asList(element.getAsString().split(","))); | ||
216 | - } else { | ||
217 | - return null; | ||
218 | - } | ||
219 | - } | ||
220 | - | ||
221 | - private static String validatePayload(UUID sessionId, ByteBuf payloadData, boolean isEmptyPayloadAllowed) throws AdaptorException { | ||
222 | - String payload = payloadData.toString(UTF8); | ||
223 | - if (payload == null) { | ||
224 | - log.debug("[{}] Payload is empty!", sessionId); | ||
225 | - if (!isEmptyPayloadAllowed) { | ||
226 | - throw new AdaptorException(new IllegalArgumentException("Payload is empty!")); | ||
227 | - } | ||
228 | - } | ||
229 | - return payload; | ||
230 | - } | ||
231 | - | ||
232 | - | ||
233 | - private int getRequestId(String topicName, String topic) { | ||
234 | - return Integer.parseInt(topicName.substring(topic.length())); | ||
235 | - } | ||
236 | - | ||
237 | - | ||
238 | - protected String createTcpMessage(GbtDeviceSessionCtx ctx, JsonElement json) { | ||
239 | -// TCPMessage msg = new TCPMessage(MqttMessageType.PUBLISH,); | ||
240 | -//// new MqttFixedHeader(MqttMessageType.PUBLISH, false, ctx.getQoSForTopic(topic), false, 0); | ||
241 | -// MqttPublishVariableHeader header = new MqttPublishVariableHeader(topic, ctx.nextMsgId()); | ||
242 | -// ByteBuf payload = ALLOCATOR.buffer(); | ||
243 | -// payload.writeBytes(json.toString().getBytes(UTF8)); | ||
244 | -// return new MqttPublishMessage(mqttFixedHeader, header, payload); | ||
245 | - return null; | ||
246 | - } | ||
247 | - | ||
248 | - | ||
249 | -} |
@@ -10,13 +10,11 @@ import javax.sip.address.AddressFactory; | @@ -10,13 +10,11 @@ import javax.sip.address.AddressFactory; | ||
10 | import javax.sip.address.SipURI; | 10 | import javax.sip.address.SipURI; |
11 | import javax.sip.header.*; | 11 | import javax.sip.header.*; |
12 | import org.springframework.beans.factory.annotation.Autowired; | 12 | import org.springframework.beans.factory.annotation.Autowired; |
13 | -import org.springframework.stereotype.Component; | ||
14 | -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig; | ||
15 | -import org.thingsboard.server.common.data.yunteng.config.media.ThingsKitVersionConfig; | ||
16 | -import org.thingsboard.server.transport.gbt28181.SipLayer; | 13 | +import org.thingsboard.server.transport.config.SipConfig; |
14 | +import org.thingsboard.server.transport.config.ThingsKitVersionConfig; | ||
15 | +import org.thingsboard.server.transport.gbt28181.sip.SipTransportService; | ||
17 | 16 | ||
18 | -@Component | ||
19 | -public class AbstractSIPRequestProcess { | 17 | +public abstract class AbstractSIPRequestProcess { |
20 | @Autowired private SipConfig sipConfig; | 18 | @Autowired private SipConfig sipConfig; |
21 | @Autowired protected ThingsKitVersionConfig thingsKitVersionConfig; | 19 | @Autowired protected ThingsKitVersionConfig thingsKitVersionConfig; |
22 | 20 | ||
@@ -41,7 +39,7 @@ public class AbstractSIPRequestProcess { | @@ -41,7 +39,7 @@ public class AbstractSIPRequestProcess { | ||
41 | ViaHeader viaHeader = | 39 | ViaHeader viaHeader = |
42 | sipFactory | 40 | sipFactory |
43 | .createHeaderFactory() | 41 | .createHeaderFactory() |
44 | - .createViaHeader(SipLayer.getLocalIp(localIp), sipConfig.getPort(), transport, viaTag); | 42 | + .createViaHeader(SipTransportService.getLocalIp(localIp), sipConfig.getPort(), transport, viaTag); |
45 | viaHeader.setRPort(); | 43 | viaHeader.setRPort(); |
46 | viaHeaders.add(viaHeader); | 44 | viaHeaders.add(viaHeader); |
47 | return viaHeaders; | 45 | return viaHeaders; |
@@ -78,7 +76,7 @@ public class AbstractSIPRequestProcess { | @@ -78,7 +76,7 @@ public class AbstractSIPRequestProcess { | ||
78 | throws PeerUnavailableException, ParseException { | 76 | throws PeerUnavailableException, ParseException { |
79 | SipURI sipUri = | 77 | SipURI sipUri = |
80 | buildRequestLineSipUri( | 78 | buildRequestLineSipUri( |
81 | - sipConfig.getId(), SipLayer.getLocalIp(localIp) + ":" + sipConfig.getPort()); | 79 | + sipConfig.getId(), SipTransportService.getLocalIp(localIp) + ":" + sipConfig.getPort()); |
82 | Address concatAddress = sipFactory.createAddressFactory().createAddress(sipUri); | 80 | Address concatAddress = sipFactory.createAddressFactory().createAddress(sipUri); |
83 | return sipFactory.createHeaderFactory().createContactHeader(concatAddress); | 81 | return sipFactory.createHeaderFactory().createContactHeader(concatAddress); |
84 | } | 82 | } |
@@ -15,12 +15,16 @@ import javax.sip.address.SipURI; | @@ -15,12 +15,16 @@ import javax.sip.address.SipURI; | ||
15 | import javax.sip.header.*; | 15 | import javax.sip.header.*; |
16 | import javax.sip.message.Request; | 16 | import javax.sip.message.Request; |
17 | import javax.sip.message.Response; | 17 | import javax.sip.message.Response; |
18 | + | ||
19 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
18 | import org.springframework.stereotype.Component; | 20 | import org.springframework.stereotype.Component; |
19 | import org.thingsboard.server.common.data.yunteng.dto.sip.SipMessageHeaderDTO; | 21 | import org.thingsboard.server.common.data.yunteng.dto.sip.SipMessageHeaderDTO; |
20 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; | 22 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; |
21 | import org.thingsboard.server.transport.util.TKSipUtils; | 23 | import org.thingsboard.server.transport.util.TKSipUtils; |
22 | 24 | ||
23 | @Component | 25 | @Component |
26 | +@ConditionalOnExpression( | ||
27 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
24 | public class SIPRequestHeaderProcess extends AbstractSIPRequestProcess { | 28 | public class SIPRequestHeaderProcess extends AbstractSIPRequestProcess { |
25 | public Request createMessageRequest( | 29 | public Request createMessageRequest( |
26 | GbtDeviceSessionCtx sessionCtx, | 30 | GbtDeviceSessionCtx sessionCtx, |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/cmd/SIPSender.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/SIPSender.java
1 | -package org.thingsboard.server.transport; | 1 | +package org.thingsboard.server.transport.cmd; |
2 | 2 | ||
3 | import gov.nist.javax.sip.SipProviderImpl; | 3 | import gov.nist.javax.sip.SipProviderImpl; |
4 | import java.text.ParseException; | 4 | import java.text.ParseException; |
@@ -11,15 +11,18 @@ import javax.sip.message.Request; | @@ -11,15 +11,18 @@ import javax.sip.message.Request; | ||
11 | import javax.sip.message.Response; | 11 | import javax.sip.message.Response; |
12 | import lombok.extern.slf4j.Slf4j; | 12 | import lombok.extern.slf4j.Slf4j; |
13 | import org.springframework.beans.factory.annotation.Autowired; | 13 | import org.springframework.beans.factory.annotation.Autowired; |
14 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
14 | import org.springframework.stereotype.Component; | 15 | import org.springframework.stereotype.Component; |
15 | import org.springframework.util.ObjectUtils; | 16 | import org.springframework.util.ObjectUtils; |
16 | -import org.thingsboard.server.common.data.yunteng.config.media.ThingsKitVersionConfig; | ||
17 | -import org.thingsboard.server.transport.gbt28181.SipLayer; | 17 | +import org.thingsboard.server.transport.config.ThingsKitVersionConfig; |
18 | +import org.thingsboard.server.transport.gbt28181.sip.SipTransportService; | ||
18 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; | 19 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; |
19 | import org.thingsboard.server.transport.util.TKSipUtils; | 20 | import org.thingsboard.server.transport.util.TKSipUtils; |
20 | 21 | ||
21 | /** 发送SIP信息 */ | 22 | /** 发送SIP信息 */ |
22 | @Component | 23 | @Component |
24 | +@ConditionalOnExpression( | ||
25 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
23 | @Slf4j | 26 | @Slf4j |
24 | public class SIPSender { | 27 | public class SIPSender { |
25 | 28 | ||
@@ -80,7 +83,7 @@ public class SIPSender { | @@ -80,7 +83,7 @@ public class SIPSender { | ||
80 | } | 83 | } |
81 | 84 | ||
82 | SipProviderImpl sipProvider = | 85 | SipProviderImpl sipProvider = |
83 | - TCP.equals(transport) ? SipLayer.getTcpSipProvider(ip) : SipLayer.getUdpSipProvider(ip); | 86 | + TCP.equals(transport) ? SipTransportService.getTcpSipProvider(ip) : SipTransportService.getUdpSipProvider(ip); |
84 | if (sipProvider == null) { | 87 | if (sipProvider == null) { |
85 | log.error("[发送信息失败] 未找到{}://{}的监听信息", transport, ip); | 88 | log.error("[发送信息失败] 未找到{}://{}的监听信息", transport, ip); |
86 | return; | 89 | return; |
@@ -94,23 +97,23 @@ public class SIPSender { | @@ -94,23 +97,23 @@ public class SIPSender { | ||
94 | 97 | ||
95 | public CallIdHeader getNewCallIdHeader(String ip, String transport) { | 98 | public CallIdHeader getNewCallIdHeader(String ip, String transport) { |
96 | if (ObjectUtils.isEmpty(transport)) { | 99 | if (ObjectUtils.isEmpty(transport)) { |
97 | - return SipLayer.getUdpSipProvider().getNewCallId(); | 100 | + return SipTransportService.getUdpSipProvider().getNewCallId(); |
98 | } | 101 | } |
99 | SipProviderImpl sipProvider; | 102 | SipProviderImpl sipProvider; |
100 | if (ObjectUtils.isEmpty(ip)) { | 103 | if (ObjectUtils.isEmpty(ip)) { |
101 | sipProvider = | 104 | sipProvider = |
102 | transport.equalsIgnoreCase(TCP) | 105 | transport.equalsIgnoreCase(TCP) |
103 | - ? SipLayer.getTcpSipProvider() | ||
104 | - : SipLayer.getUdpSipProvider(); | 106 | + ? SipTransportService.getTcpSipProvider() |
107 | + : SipTransportService.getUdpSipProvider(); | ||
105 | } else { | 108 | } else { |
106 | sipProvider = | 109 | sipProvider = |
107 | transport.equalsIgnoreCase(TCP) | 110 | transport.equalsIgnoreCase(TCP) |
108 | - ? SipLayer.getTcpSipProvider(ip) | ||
109 | - : SipLayer.getUdpSipProvider(ip); | 111 | + ? SipTransportService.getTcpSipProvider(ip) |
112 | + : SipTransportService.getUdpSipProvider(ip); | ||
110 | } | 113 | } |
111 | 114 | ||
112 | if (sipProvider == null) { | 115 | if (sipProvider == null) { |
113 | - sipProvider = SipLayer.getUdpSipProvider(); | 116 | + sipProvider = SipTransportService.getUdpSipProvider(); |
114 | } | 117 | } |
115 | 118 | ||
116 | if (sipProvider != null) { | 119 | if (sipProvider != null) { |
@@ -13,8 +13,7 @@ import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | @@ -13,8 +13,7 @@ import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | ||
13 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 13 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
14 | import org.thingsboard.server.common.data.yunteng.dto.sip.*; | 14 | import org.thingsboard.server.common.data.yunteng.dto.sip.*; |
15 | import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum; | 15 | import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum; |
16 | -import org.thingsboard.server.transport.SIPSender; | ||
17 | -import org.thingsboard.server.transport.gbt28181.SipLayer; | 16 | +import org.thingsboard.server.transport.gbt28181.sip.SipTransportService; |
18 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; | 17 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; |
19 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; | 18 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; |
20 | import org.thingsboard.server.transport.util.TKSipUtils; | 19 | import org.thingsboard.server.transport.util.TKSipUtils; |
@@ -41,11 +40,11 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | @@ -41,11 +40,11 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | ||
41 | sessionCtx.getCameraCode()); | 40 | sessionCtx.getCameraCode()); |
42 | CallIdHeader callIdHeader = | 41 | CallIdHeader callIdHeader = |
43 | sipSender.getNewCallIdHeader( | 42 | sipSender.getNewCallIdHeader( |
44 | - SipLayer.getLocalIp(sessionCtx.getLocalIp()), sessionCtx.getTransport()); | 43 | + SipTransportService.getLocalIp(sessionCtx.getLocalIp()), sessionCtx.getTransport()); |
45 | Request request = | 44 | Request request = |
46 | headerProvider.createMessageRequest( | 45 | headerProvider.createMessageRequest( |
47 | sessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); | 46 | sessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); |
48 | - sipSender.transmitRequest(SipLayer.getLocalIp(sessionCtx.getLocalIp()), request); | 47 | + sipSender.transmitRequest(SipTransportService.getLocalIp(sessionCtx.getLocalIp()), request); |
49 | } | 48 | } |
50 | 49 | ||
51 | @Override | 50 | @Override |
@@ -63,13 +62,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | @@ -63,13 +62,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | ||
63 | deviceSessionCtx.getCameraCode()); | 62 | deviceSessionCtx.getCameraCode()); |
64 | CallIdHeader callIdHeader = | 63 | CallIdHeader callIdHeader = |
65 | sipSender.getNewCallIdHeader( | 64 | sipSender.getNewCallIdHeader( |
66 | - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); | 65 | + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); |
67 | Request request = | 66 | Request request = |
68 | headerProvider.createMessageRequest( | 67 | headerProvider.createMessageRequest( |
69 | deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); | 68 | deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); |
70 | 69 | ||
71 | sipSender.transmitRequest( | 70 | sipSender.transmitRequest( |
72 | - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), request, errorEvent); | 71 | + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), request, errorEvent); |
73 | } | 72 | } |
74 | 73 | ||
75 | @Override | 74 | @Override |
@@ -86,12 +85,12 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | @@ -86,12 +85,12 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | ||
86 | ptzCmd); | 85 | ptzCmd); |
87 | CallIdHeader callIdHeader = | 86 | CallIdHeader callIdHeader = |
88 | sipSender.getNewCallIdHeader( | 87 | sipSender.getNewCallIdHeader( |
89 | - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); | 88 | + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); |
90 | Request request = | 89 | Request request = |
91 | headerProvider.createMessageRequest( | 90 | headerProvider.createMessageRequest( |
92 | deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); | 91 | deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); |
93 | 92 | ||
94 | - sipSender.transmitRequest(SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), request); | 93 | + sipSender.transmitRequest(SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), request); |
95 | } | 94 | } |
96 | 95 | ||
97 | @Override | 96 | @Override |
@@ -110,13 +109,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | @@ -110,13 +109,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | ||
110 | 109 | ||
111 | CallIdHeader callIdHeader = | 110 | CallIdHeader callIdHeader = |
112 | sipSender.getNewCallIdHeader( | 111 | sipSender.getNewCallIdHeader( |
113 | - SipLayer.getLocalIp(devSession.getLocalIp()), devSession.getTransport()); | 112 | + SipTransportService.getLocalIp(devSession.getLocalIp()), devSession.getTransport()); |
114 | Request request = | 113 | Request request = |
115 | headerProvider.createInviteRequest( | 114 | headerProvider.createInviteRequest( |
116 | devSession, sipMessageHeaderDTO, channelId, content, callIdHeader, ssrc); | 115 | devSession, sipMessageHeaderDTO, channelId, content, callIdHeader, ssrc); |
117 | 116 | ||
118 | sipSender.transmitRequest( | 117 | sipSender.transmitRequest( |
119 | - SipLayer.getLocalIp(devSession.getLocalIp()), request, errorEvent, okEvent); | 118 | + SipTransportService.getLocalIp(devSession.getLocalIp()), request, errorEvent, okEvent); |
120 | } | 119 | } |
121 | 120 | ||
122 | @Override | 121 | @Override |
@@ -144,7 +143,7 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | @@ -144,7 +143,7 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { | ||
144 | headerDTO.getViaTag(), | 143 | headerDTO.getViaTag(), |
145 | headerDTO.getFromTag(), | 144 | headerDTO.getFromTag(), |
146 | headerDTO.getToTag()); | 145 | headerDTO.getToTag()); |
147 | - sipSender.transmitRequest(SipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); | 146 | + sipSender.transmitRequest(SipTransportService.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); |
148 | } | 147 | } |
149 | 148 | ||
150 | private String buildMessageBodyQueryXml( | 149 | private String buildMessageBodyQueryXml( |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/config/MediaConfig.java
0 → 100644
1 | +package org.thingsboard.server.transport.config; | ||
2 | + | ||
3 | +import java.io.Serializable; | ||
4 | +import lombok.Data; | ||
5 | +import lombok.extern.slf4j.Slf4j; | ||
6 | +import org.springframework.beans.factory.annotation.Value; | ||
7 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
8 | +import org.springframework.boot.context.properties.ConfigurationProperties; | ||
9 | +import org.springframework.stereotype.Component; | ||
10 | + | ||
11 | +/** 配置文件里面的流媒体配置信息 */ | ||
12 | +@ConfigurationProperties(prefix = "transport.gbt28181.media") | ||
13 | +@Component | ||
14 | +@ConditionalOnExpression( | ||
15 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
16 | +@Data | ||
17 | +@Slf4j | ||
18 | +public class MediaConfig implements Serializable { | ||
19 | + @Value("${transport.gbt28181.media.id}") | ||
20 | + private String mediaServerId; | ||
21 | + | ||
22 | + @Value("${transport.gbt28181.media.ip}") | ||
23 | + private String ip; | ||
24 | + | ||
25 | + @Value("${transport.gbt28181.media.hook-ip:}") | ||
26 | + private String hookIp; | ||
27 | + | ||
28 | + @Value("${transport.gbt28181.media.sdp-ip:${transport.gbt28181.media.ip}}") | ||
29 | + private String sdpIp; | ||
30 | + | ||
31 | + @Value("${transport.gbt28181.media.stream-ip:${transport.gbt28181.media.ip}}") | ||
32 | + private String streamIp; | ||
33 | + | ||
34 | + @Value("${transport.gbt28181.media.http-port}") | ||
35 | + private Integer httpPort; | ||
36 | + | ||
37 | + @Value("${transport.gbt28181.media.http-ssl-port:0}") | ||
38 | + private Integer httpSslPort = 0; | ||
39 | + | ||
40 | + @Value("${transport.gbt28181.media.rtmp-port:0}") | ||
41 | + private Integer rtmpPort = 0; | ||
42 | + | ||
43 | + @Value("${transport.gbt28181.media.rtmp-ssl-port:0}") | ||
44 | + private Integer rtmpSslPort = 0; | ||
45 | + | ||
46 | + @Value("${transport.gbt28181.media.rtp-proxy-port:0}") | ||
47 | + private Integer rtpProxyPort = 0; | ||
48 | + | ||
49 | + @Value("${transport.gbt28181.media.rtsp-port:0}") | ||
50 | + private Integer rtspPort = 0; | ||
51 | + | ||
52 | + @Value("${transport.gbt28181.media.rtsp-ssl-port:0}") | ||
53 | + private Integer rtspSslPort = 0; | ||
54 | + | ||
55 | + @Value("${transport.gbt28181.media.auto-config:true}") | ||
56 | + private boolean autoConfig = true; | ||
57 | + | ||
58 | + @Value("${transport.gbt28181.media.secret}") | ||
59 | + private String secret; | ||
60 | + | ||
61 | + @Value("${transport.gbt28181.media.rtp.enable}") | ||
62 | + private boolean rtpEnable; | ||
63 | + | ||
64 | + @Value("${transport.gbt28181.media.rtp.port-range}") | ||
65 | + private String rtpPortRange; | ||
66 | + | ||
67 | + @Value("${transport.gbt28181.media.rtp.send-port-range}") | ||
68 | + private String rtpSendPortRange; | ||
69 | + | ||
70 | + @Value("${transport.gbt28181.media.record-assist-port:0}") | ||
71 | + private Integer recordAssistPort = 0; | ||
72 | + | ||
73 | + private boolean status; | ||
74 | +} |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/config/SipConfig.java
renamed from
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/config/media/SipConfig.java
1 | -package org.thingsboard.server.common.data.yunteng.config.media; | 1 | +package org.thingsboard.server.transport.config; |
2 | 2 | ||
3 | import lombok.Data; | 3 | import lombok.Data; |
4 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
4 | import org.springframework.boot.context.properties.ConfigurationProperties; | 5 | import org.springframework.boot.context.properties.ConfigurationProperties; |
5 | import org.springframework.stereotype.Component; | 6 | import org.springframework.stereotype.Component; |
6 | 7 | ||
7 | -@ConfigurationProperties(prefix = "sip") | 8 | +@ConfigurationProperties(prefix = "transport.gbt28181.sip") |
8 | @Component | 9 | @Component |
10 | +@ConditionalOnExpression( | ||
11 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
9 | @Data | 12 | @Data |
10 | public class SipConfig { | 13 | public class SipConfig { |
11 | - private String ip; | ||
12 | - private String showIp; | ||
13 | - private Integer port; | ||
14 | - private String id; | ||
15 | - private String domain; | ||
16 | - private String password; | ||
17 | - Integer ptzSpeed = 50; | ||
18 | - Integer registerTimeInterval = 120; | ||
19 | - private boolean alarm; | 14 | + private String ip; |
15 | + private String showIp; | ||
16 | + private Integer port; | ||
17 | + private String id; | ||
18 | + private String domain; | ||
19 | + private String password; | ||
20 | + Integer ptzSpeed = 50; | ||
21 | + Integer registerTimeInterval = 120; | ||
22 | + private boolean alarm; | ||
20 | 23 | ||
21 | - public String getShowIp() { | ||
22 | - if (this.showIp == null) { | ||
23 | - return this.ip; | ||
24 | - } | ||
25 | - return showIp; | 24 | + public String getShowIp() { |
25 | + if (this.showIp == null) { | ||
26 | + return this.ip; | ||
26 | } | 27 | } |
28 | + return showIp; | ||
29 | + } | ||
27 | } | 30 | } |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/config/ThingsKitVersionConfig.java
renamed from
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/config/media/ThingsKitVersionConfig.java
1 | -package org.thingsboard.server.common.data.yunteng.config.media; | 1 | +package org.thingsboard.server.transport.config; |
2 | 2 | ||
3 | import lombok.Data; | 3 | import lombok.Data; |
4 | import org.springframework.beans.factory.annotation.Value; | 4 | import org.springframework.beans.factory.annotation.Value; |
5 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
5 | import org.springframework.stereotype.Component; | 6 | import org.springframework.stereotype.Component; |
6 | 7 | ||
7 | @Component | 8 | @Component |
9 | +@ConditionalOnExpression( | ||
10 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
8 | @Data | 11 | @Data |
9 | public class ThingsKitVersionConfig { | 12 | public class ThingsKitVersionConfig { |
10 | @Value("${thingskit.release.version}") | 13 | @Value("${thingskit.release.version}") |
@@ -13,12 +13,15 @@ import javax.sip.header.CallIdHeader; | @@ -13,12 +13,15 @@ import javax.sip.header.CallIdHeader; | ||
13 | import javax.sip.message.Response; | 13 | import javax.sip.message.Response; |
14 | import org.slf4j.Logger; | 14 | import org.slf4j.Logger; |
15 | import org.slf4j.LoggerFactory; | 15 | import org.slf4j.LoggerFactory; |
16 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
16 | import org.springframework.scheduling.annotation.Scheduled; | 17 | import org.springframework.scheduling.annotation.Scheduled; |
17 | import org.springframework.stereotype.Component; | 18 | import org.springframework.stereotype.Component; |
18 | -import org.thingsboard.server.transport.gbt28181.event.DeviceNotFoundEvent; | 19 | +import org.thingsboard.server.transport.gbt28181.sip.event.DeviceNotFoundEvent; |
19 | 20 | ||
20 | /** SIP订阅信息 */ | 21 | /** SIP订阅信息 */ |
21 | @Component | 22 | @Component |
23 | +@ConditionalOnExpression( | ||
24 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
22 | public class SipSubscribe { | 25 | public class SipSubscribe { |
23 | 26 | ||
24 | private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class); | 27 | private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class); |
@@ -36,8 +36,6 @@ import javax.sip.header.HeaderFactory; | @@ -36,8 +36,6 @@ import javax.sip.header.HeaderFactory; | ||
36 | import javax.sip.header.WWWAuthenticateHeader; | 36 | import javax.sip.header.WWWAuthenticateHeader; |
37 | import javax.sip.message.Request; | 37 | import javax.sip.message.Request; |
38 | import javax.sip.message.Response; | 38 | import javax.sip.message.Response; |
39 | -import org.slf4j.Logger; | ||
40 | -import org.slf4j.LoggerFactory; | ||
41 | 39 | ||
42 | /** Implements the HTTP digest authentication method server side functionality. */ | 40 | /** Implements the HTTP digest authentication method server side functionality. */ |
43 | public class DigestServerAuthenticationHelper { | 41 | public class DigestServerAuthenticationHelper { |
@@ -99,6 +97,7 @@ public class DigestServerAuthenticationHelper { | @@ -99,6 +97,7 @@ public class DigestServerAuthenticationHelper { | ||
99 | } | 97 | } |
100 | return response; | 98 | return response; |
101 | } | 99 | } |
100 | + | ||
102 | /** | 101 | /** |
103 | * Authenticate the inbound request. | 102 | * Authenticate the inbound request. |
104 | * | 103 | * |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/auth/RemoteAddressInfo.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/info/RemoteAddressInfo.java
1 | -package org.thingsboard.server.transport.info; | 1 | +package org.thingsboard.server.transport.gbt28181.auth; |
2 | 2 | ||
3 | +import lombok.Data; | ||
4 | + | ||
5 | +@Data | ||
3 | public class RemoteAddressInfo { | 6 | public class RemoteAddressInfo { |
4 | private String ip; | 7 | private String ip; |
5 | private int port; | 8 | private int port; |
@@ -8,20 +11,4 @@ public class RemoteAddressInfo { | @@ -8,20 +11,4 @@ public class RemoteAddressInfo { | ||
8 | this.ip = ip; | 11 | this.ip = ip; |
9 | this.port = port; | 12 | this.port = port; |
10 | } | 13 | } |
11 | - | ||
12 | - public String getIp() { | ||
13 | - return ip; | ||
14 | - } | ||
15 | - | ||
16 | - public void setIp(String ip) { | ||
17 | - this.ip = ip; | ||
18 | - } | ||
19 | - | ||
20 | - public int getPort() { | ||
21 | - return port; | ||
22 | - } | ||
23 | - | ||
24 | - public void setPort(int port) { | ||
25 | - this.port = port; | ||
26 | - } | ||
27 | } | 14 | } |
@@ -7,6 +7,7 @@ import java.util.*; | @@ -7,6 +7,7 @@ import java.util.*; | ||
7 | import java.util.concurrent.ConcurrentHashMap; | 7 | import java.util.concurrent.ConcurrentHashMap; |
8 | import java.util.concurrent.TimeUnit; | 8 | import java.util.concurrent.TimeUnit; |
9 | 9 | ||
10 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
10 | import org.springframework.scheduling.annotation.Scheduled; | 11 | import org.springframework.scheduling.annotation.Scheduled; |
11 | import org.springframework.stereotype.Component; | 12 | import org.springframework.stereotype.Component; |
12 | import org.thingsboard.server.common.data.yunteng.dto.sip.CatalogDataDTO; | 13 | import org.thingsboard.server.common.data.yunteng.dto.sip.CatalogDataDTO; |
@@ -16,6 +17,8 @@ import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; | @@ -16,6 +17,8 @@ import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; | ||
16 | import org.thingsboard.server.common.data.yunteng.enums.CatalogDataStatusEnum; | 17 | import org.thingsboard.server.common.data.yunteng.enums.CatalogDataStatusEnum; |
17 | 18 | ||
18 | @Component | 19 | @Component |
20 | +@ConditionalOnExpression( | ||
21 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
19 | public class CatalogDataCatch { | 22 | public class CatalogDataCatch { |
20 | 23 | ||
21 | public static Map<String, CatalogDataDTO> data = new ConcurrentHashMap<>(); | 24 | public static Map<String, CatalogDataDTO> data = new ConcurrentHashMap<>(); |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/session/GbtTransportContext.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/GbtTransportContext.java
1 | -package org.thingsboard.server.transport; | 1 | +package org.thingsboard.server.transport.gbt28181.session; |
2 | 2 | ||
3 | -import gov.nist.core.HostPort; | ||
4 | import io.netty.handler.ssl.SslHandler; | 3 | import io.netty.handler.ssl.SslHandler; |
5 | -import java.net.InetSocketAddress; | ||
6 | import java.util.concurrent.Executors; | 4 | import java.util.concurrent.Executors; |
7 | import java.util.concurrent.ScheduledExecutorService; | 5 | import java.util.concurrent.ScheduledExecutorService; |
8 | import java.util.concurrent.atomic.AtomicInteger; | 6 | import java.util.concurrent.atomic.AtomicInteger; |
@@ -10,13 +8,11 @@ import javax.annotation.PostConstruct; | @@ -10,13 +8,11 @@ import javax.annotation.PostConstruct; | ||
10 | import lombok.Getter; | 8 | import lombok.Getter; |
11 | import lombok.Setter; | 9 | import lombok.Setter; |
12 | import lombok.extern.slf4j.Slf4j; | 10 | import lombok.extern.slf4j.Slf4j; |
13 | -import org.springframework.beans.factory.annotation.Autowired; | ||
14 | import org.springframework.beans.factory.annotation.Value; | 11 | import org.springframework.beans.factory.annotation.Value; |
15 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 12 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
16 | import org.springframework.stereotype.Component; | 13 | import org.springframework.stereotype.Component; |
17 | import org.thingsboard.common.util.ThingsBoardThreadFactory; | 14 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
18 | import org.thingsboard.server.common.transport.TransportContext; | 15 | import org.thingsboard.server.common.transport.TransportContext; |
19 | -import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor; | ||
20 | 16 | ||
21 | @Slf4j | 17 | @Slf4j |
22 | @Component | 18 | @Component |
@@ -24,8 +20,6 @@ import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor; | @@ -24,8 +20,6 @@ import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor; | ||
24 | "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | 20 | "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") |
25 | public class GbtTransportContext extends TransportContext { | 21 | public class GbtTransportContext extends TransportContext { |
26 | 22 | ||
27 | - /** 注入多种数据协议处理器,例如:modbus等 */ | ||
28 | - @Getter @Autowired private GbtTransportAdaptor jsonAdaptor; | ||
29 | 23 | ||
30 | @Getter | 24 | @Getter |
31 | @Value("${transport.tcp.netty.max_payload_size}") | 25 | @Value("${transport.tcp.netty.max_payload_size}") |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/DefaultProperties.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/DefaultProperties.java
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/ISIPRequestProcessor.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/ISIPRequestProcessor.java
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/ISIPResponseProcessor.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/ISIPResponseProcessor.java
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/SipTransportService.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/SipLayer.java
@@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
11 | * express or implied. See the License for the specific language governing permissions and | 11 | * express or implied. See the License for the specific language governing permissions and |
12 | * limitations under the License. | 12 | * limitations under the License. |
13 | */ | 13 | */ |
14 | -package org.thingsboard.server.transport.gbt28181; | 14 | +package org.thingsboard.server.transport.gbt28181.sip; |
15 | 15 | ||
16 | import gov.nist.javax.sip.SipProviderImpl; | 16 | import gov.nist.javax.sip.SipProviderImpl; |
17 | import gov.nist.javax.sip.SipStackImpl; | 17 | import gov.nist.javax.sip.SipStackImpl; |
@@ -26,20 +26,20 @@ import org.springframework.stereotype.Service; | @@ -26,20 +26,20 @@ import org.springframework.stereotype.Service; | ||
26 | import org.springframework.util.ObjectUtils; | 26 | import org.springframework.util.ObjectUtils; |
27 | import org.thingsboard.server.common.data.DataConstants; | 27 | import org.thingsboard.server.common.data.DataConstants; |
28 | import org.thingsboard.server.common.data.TbTransportService; | 28 | import org.thingsboard.server.common.data.TbTransportService; |
29 | -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig; | ||
30 | -import org.thingsboard.server.transport.SIPProvider; | 29 | +import org.thingsboard.server.transport.gbt28181.sip.processor.SIPProvider; |
30 | +import org.thingsboard.server.transport.config.SipConfig; | ||
31 | 31 | ||
32 | /** | 32 | /** |
33 | * @author Andrew Shvayka | 33 | * @author Andrew Shvayka |
34 | */ | 34 | */ |
35 | -@Service("GBT28181TransportService") | ||
36 | -@ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | 35 | +@Service() |
36 | +@ConditionalOnExpression( | ||
37 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
37 | @Slf4j | 38 | @Slf4j |
38 | -public class SipLayer implements TbTransportService { | 39 | +public class SipTransportService implements TbTransportService { |
39 | private static final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); | 40 | private static final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); |
40 | private static final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); | 41 | private static final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); |
41 | - @Autowired | ||
42 | - private SIPProvider sipProvider; | 42 | + @Autowired private SIPProvider sipProvider; |
43 | 43 | ||
44 | @Autowired private SipConfig sipConfig; | 44 | @Autowired private SipConfig sipConfig; |
45 | 45 |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/event/DeviceNotFoundEvent.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/event/DeviceNotFoundEvent.java
1 | -package org.thingsboard.server.transport.gbt28181.event; | 1 | +package org.thingsboard.server.transport.gbt28181.sip.event; |
2 | 2 | ||
3 | import java.util.EventObject; | 3 | import java.util.EventObject; |
4 | import javax.sip.Dialog; | 4 | import javax.sip.Dialog; |
5 | +import lombok.Getter; | ||
6 | +import lombok.Setter; | ||
5 | 7 | ||
8 | +@Getter | ||
9 | +@Setter | ||
6 | public class DeviceNotFoundEvent extends EventObject { | 10 | public class DeviceNotFoundEvent extends EventObject { |
7 | 11 | ||
8 | private String callId; | 12 | private String callId; |
@@ -16,12 +20,4 @@ public class DeviceNotFoundEvent extends EventObject { | @@ -16,12 +20,4 @@ public class DeviceNotFoundEvent extends EventObject { | ||
16 | public DeviceNotFoundEvent(Dialog dialog) { | 20 | public DeviceNotFoundEvent(Dialog dialog) { |
17 | super(dialog); | 21 | super(dialog); |
18 | } | 22 | } |
19 | - | ||
20 | - public String getCallId() { | ||
21 | - return callId; | ||
22 | - } | ||
23 | - | ||
24 | - public void setCallId(String callId) { | ||
25 | - this.callId = callId; | ||
26 | - } | ||
27 | } | 23 | } |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/ITimeoutProcessor.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/ITimeoutProcessor.java
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/SIPProcessorObserver.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/SIPProcessorObserver.java
1 | -package org.thingsboard.server.transport; | 1 | +package org.thingsboard.server.transport.gbt28181.sip.processor; |
2 | 2 | ||
3 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED; | 3 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED; |
4 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_OPEN; | 4 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_OPEN; |
@@ -40,8 +40,6 @@ import org.thingsboard.server.common.data.DeviceTransportType; | @@ -40,8 +40,6 @@ import org.thingsboard.server.common.data.DeviceTransportType; | ||
40 | import org.thingsboard.server.common.data.StringUtils; | 40 | import org.thingsboard.server.common.data.StringUtils; |
41 | import org.thingsboard.server.common.data.id.DeviceId; | 41 | import org.thingsboard.server.common.data.id.DeviceId; |
42 | import org.thingsboard.server.common.data.rpc.RpcStatus; | 42 | import org.thingsboard.server.common.data.rpc.RpcStatus; |
43 | -import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; | ||
44 | -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig; | ||
45 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | 43 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
46 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 44 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
47 | import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; | 45 | import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; |
@@ -58,11 +56,16 @@ import org.thingsboard.server.common.transport.auth.SessionInfoCreator; | @@ -58,11 +56,16 @@ import org.thingsboard.server.common.transport.auth.SessionInfoCreator; | ||
58 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; | 56 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
59 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; | 57 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; |
60 | import org.thingsboard.server.gen.transport.TransportProtos; | 58 | import org.thingsboard.server.gen.transport.TransportProtos; |
59 | +import org.thingsboard.server.transport.gbt28181.session.GbtTransportContext; | ||
61 | import org.thingsboard.server.transport.cmd.SIPRequestHeaderProcess; | 60 | import org.thingsboard.server.transport.cmd.SIPRequestHeaderProcess; |
62 | import org.thingsboard.server.transport.cmd.TKSipCommanderService; | 61 | import org.thingsboard.server.transport.cmd.TKSipCommanderService; |
62 | +import org.thingsboard.server.transport.config.MediaConfig; | ||
63 | +import org.thingsboard.server.transport.config.SipConfig; | ||
63 | import org.thingsboard.server.transport.gbt28181.*; | 64 | import org.thingsboard.server.transport.gbt28181.*; |
64 | import org.thingsboard.server.transport.gbt28181.auth.DigestServerAuthenticationHelper; | 65 | import org.thingsboard.server.transport.gbt28181.auth.DigestServerAuthenticationHelper; |
65 | -import org.thingsboard.server.transport.info.RemoteAddressInfo; | 66 | +import org.thingsboard.server.transport.gbt28181.sip.ISIPRequestProcessor; |
67 | +import org.thingsboard.server.transport.gbt28181.sip.ISIPResponseProcessor; | ||
68 | +import org.thingsboard.server.transport.gbt28181.auth.RemoteAddressInfo; | ||
66 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; | 69 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; |
67 | import org.thingsboard.server.transport.util.TKSipUtils; | 70 | import org.thingsboard.server.transport.util.TKSipUtils; |
68 | import org.thingsboard.server.transport.util.TKXmlUtil; | 71 | import org.thingsboard.server.transport.util.TKXmlUtil; |
@@ -81,6 +84,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -81,6 +84,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
81 | 84 | ||
82 | private final SIPRequestHeaderProcess headerProvider; | 85 | private final SIPRequestHeaderProcess headerProvider; |
83 | private final SipConfig sipConfig; | 86 | private final SipConfig sipConfig; |
87 | + private final MediaConfig mediaConfig; | ||
84 | private final UserSetting userSetting; | 88 | private final UserSetting userSetting; |
85 | private final TKSipCommanderService commanderService; | 89 | private final TKSipCommanderService commanderService; |
86 | private final DataDecodingEncodingService encodingService; | 90 | private final DataDecodingEncodingService encodingService; |
@@ -93,7 +97,9 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -93,7 +97,9 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
93 | 97 | ||
94 | @Getter | 98 | @Getter |
95 | private final ConcurrentHashMap<DeviceId, String> onlineDevice = new ConcurrentHashMap<>(); | 99 | private final ConcurrentHashMap<DeviceId, String> onlineDevice = new ConcurrentHashMap<>(); |
96 | - private final ConcurrentHashMap<String, List<VideoChanelDTO>> deviceNewChanel = new ConcurrentHashMap<>(); | 100 | + |
101 | + private final ConcurrentHashMap<String, List<VideoChanelDTO>> deviceNewChanel = | ||
102 | + new ConcurrentHashMap<>(); | ||
97 | private static final Map<String, ISIPRequestProcessor> requestProcessorMap = | 103 | private static final Map<String, ISIPRequestProcessor> requestProcessorMap = |
98 | new ConcurrentHashMap<>(); | 104 | new ConcurrentHashMap<>(); |
99 | private static final Map<String, ISIPResponseProcessor> responseProcessorMap = | 105 | private static final Map<String, ISIPResponseProcessor> responseProcessorMap = |
@@ -101,6 +107,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -101,6 +107,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
101 | private static ITimeoutProcessor timeoutProcessor; | 107 | private static ITimeoutProcessor timeoutProcessor; |
102 | 108 | ||
103 | private final SipSubscribe sipSubscribe; | 109 | private final SipSubscribe sipSubscribe; |
110 | + | ||
104 | /** | 111 | /** |
105 | * 添加 request订阅 | 112 | * 添加 request订阅 |
106 | * | 113 | * |
@@ -159,7 +166,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -159,7 +166,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
159 | CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); | 166 | CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); |
160 | String methodName = cseqHeader.getMethod(); | 167 | String methodName = cseqHeader.getMethod(); |
161 | SIPResponse request = (SIPResponse) responseEvent.getResponse(); | 168 | SIPResponse request = (SIPResponse) responseEvent.getResponse(); |
162 | - log.debug( | 169 | + log.info( |
163 | "收到ResponseEvent,方法类型【{}】,状态码【{}】,事件内容【{}】", | 170 | "收到ResponseEvent,方法类型【{}】,状态码【{}】,事件内容【{}】", |
164 | methodName, | 171 | methodName, |
165 | status, | 172 | status, |
@@ -178,8 +185,11 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -178,8 +185,11 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
178 | default: | 185 | default: |
179 | log.debug("不支持的响应类型【{}】", method); | 186 | log.debug("不支持的响应类型【{}】", method); |
180 | } | 187 | } |
181 | - if (status != Response.UNAUTHORIZED && responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) { | ||
182 | - CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); | 188 | + if (status != Response.UNAUTHORIZED |
189 | + && responseEvent.getResponse() != null | ||
190 | + && sipSubscribe.getOkSubscribesSize() > 0) { | ||
191 | + CallIdHeader callIdHeader = | ||
192 | + (CallIdHeader) responseEvent.getResponse().getHeader(CallIdHeader.NAME); | ||
183 | if (callIdHeader != null) { | 193 | if (callIdHeader != null) { |
184 | SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); | 194 | SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); |
185 | if (subscribe != null) { | 195 | if (subscribe != null) { |
@@ -192,20 +202,26 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -192,20 +202,26 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
192 | } else if ((status >= Response.TRYING) && (status < Response.OK)) { | 202 | } else if ((status >= Response.TRYING) && (status < Response.OK)) { |
193 | // 增加其它无需回复的响应,如101、180等 | 203 | // 增加其它无需回复的响应,如101、180等 |
194 | } else { | 204 | } else { |
195 | - log.error("收到ResponseEvent,设备【{}】,状态码【{}】,失败原因【{}】,ResponseEvent内容【{}】",response.getHeader(FromHeader.NAME),status, response.getReasonPhrase(),response.getRawContent() == null ? null : new String(response.getRawContent())); | ||
196 | - if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) { | ||
197 | - CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); | ||
198 | - if (callIdHeader != null) { | ||
199 | - SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); | ||
200 | - if (subscribe != null) { | ||
201 | - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); | ||
202 | - subscribe.response(eventResult); | ||
203 | - sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId()); | ||
204 | - } | 205 | + log.error( |
206 | + "收到ResponseEvent,设备【{}】,状态码【{}】,失败原因【{}】,ResponseEvent内容【{}】", | ||
207 | + response.getHeader(FromHeader.NAME), | ||
208 | + status, | ||
209 | + response.getReasonPhrase(), | ||
210 | + response.getRawContent() == null ? null : new String(response.getRawContent())); | ||
211 | + if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0) { | ||
212 | + CallIdHeader callIdHeader = | ||
213 | + (CallIdHeader) responseEvent.getResponse().getHeader(CallIdHeader.NAME); | ||
214 | + if (callIdHeader != null) { | ||
215 | + SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); | ||
216 | + if (subscribe != null) { | ||
217 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); | ||
218 | + subscribe.response(eventResult); | ||
219 | + sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId()); | ||
205 | } | 220 | } |
221 | + } | ||
206 | } | 222 | } |
207 | if (responseEvent.getDialog() != null) { | 223 | if (responseEvent.getDialog() != null) { |
208 | - responseEvent.getDialog().delete(); | 224 | + responseEvent.getDialog().delete(); |
209 | } | 225 | } |
210 | } | 226 | } |
211 | } | 227 | } |
@@ -219,7 +235,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -219,7 +235,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
219 | public void processRequest(RequestEvent requestEvent) { | 235 | public void processRequest(RequestEvent requestEvent) { |
220 | String methodName = requestEvent.getRequest().getMethod(); | 236 | String methodName = requestEvent.getRequest().getMethod(); |
221 | SIPRequest request = (SIPRequest) requestEvent.getRequest(); | 237 | SIPRequest request = (SIPRequest) requestEvent.getRequest(); |
222 | - log.debug( | 238 | + log.info( |
223 | "收到RequestEvent,方法类型【{}】,事件内容【{}】", | 239 | "收到RequestEvent,方法类型【{}】,事件内容【{}】", |
224 | methodName, | 240 | methodName, |
225 | request.getRawContent() == null ? null : new String(request.getRawContent())); | 241 | request.getRawContent() == null ? null : new String(request.getRawContent())); |
@@ -307,14 +323,15 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -307,14 +323,15 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
307 | */ | 323 | */ |
308 | void processResponseMessage(GbtDeviceSessionCtx ctx, ResponseEvent msg) {} | 324 | void processResponseMessage(GbtDeviceSessionCtx ctx, ResponseEvent msg) {} |
309 | 325 | ||
310 | - private String cameraAddress(SIPRequest request){ | 326 | + private String cameraAddress(SIPRequest request) { |
311 | RemoteAddressInfo remoteAddressInfo = | 327 | RemoteAddressInfo remoteAddressInfo = |
312 | - TKSipUtils.getRemoteAddressFromRequest( | ||
313 | - request, userSetting.getSipUseSourceIpAsRemoteAddress()); | 328 | + TKSipUtils.getRemoteAddressFromRequest( |
329 | + request, userSetting.getSipUseSourceIpAsRemoteAddress()); | ||
314 | String hostAddress = remoteAddressInfo.getIp(); | 330 | String hostAddress = remoteAddressInfo.getIp(); |
315 | int remotePort = remoteAddressInfo.getPort(); | 331 | int remotePort = remoteAddressInfo.getPort(); |
316 | return hostAddress + ":" + remotePort; | 332 | return hostAddress + ":" + remotePort; |
317 | } | 333 | } |
334 | + | ||
318 | /** | 335 | /** |
319 | * 处理请求事件的MESSAGE消息,根据XML数据的根节点名称进行分发 | 336 | * 处理请求事件的MESSAGE消息,根据XML数据的根节点名称进行分发 |
320 | * | 337 | * |
@@ -342,7 +359,8 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -342,7 +359,8 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
342 | } | 359 | } |
343 | if (ctx != null) { | 360 | if (ctx != null) { |
344 | if (!ctx.getHostAddress().equals(cameraAddress(request))) { | 361 | if (!ctx.getHostAddress().equals(cameraAddress(request))) { |
345 | - log.trace("摄像头【{}/{}】IP或端口已过期,断开连接", ctx.getDeviceInfo().getDeviceName(),ctx.getCameraCode()); | 362 | + log.trace( |
363 | + "摄像头【{}/{}】IP或端口已过期,断开连接", ctx.getDeviceInfo().getDeviceName(), ctx.getCameraCode()); | ||
346 | deviceSessions.remove(ctx.getCameraCode()); | 364 | deviceSessions.remove(ctx.getCameraCode()); |
347 | responseAck(request, Response.OK); | 365 | responseAck(request, Response.OK); |
348 | return; | 366 | return; |
@@ -454,7 +472,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -454,7 +472,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
454 | transportService.deregisterSession(ds.getSessionInfo()); | 472 | transportService.deregisterSession(ds.getSessionInfo()); |
455 | transportService.process(ds.getSessionInfo(), SESSION_EVENT_MSG_CLOSED, null); | 473 | transportService.process(ds.getSessionInfo(), SESSION_EVENT_MSG_CLOSED, null); |
456 | try { | 474 | try { |
457 | - cameraResponseRequest(ds, request, null,null); | 475 | + cameraResponseRequest(ds, request, null, null); |
458 | } catch (InvalidArgumentException | ParseException | SipException e) { | 476 | } catch (InvalidArgumentException | ParseException | SipException e) { |
459 | throw new RuntimeException(e); | 477 | throw new RuntimeException(e); |
460 | } | 478 | } |
@@ -515,24 +533,25 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -515,24 +533,25 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
515 | case DeviceInfo: | 533 | case DeviceInfo: |
516 | SipDeviceDTO cameraInfoDTO = TKXmlUtil.cameraInfoBuilder(rootElement); | 534 | SipDeviceDTO cameraInfoDTO = TKXmlUtil.cameraInfoBuilder(rootElement); |
517 | cameraInfoDTO.setHostAddress(request.getViaHost() + ":" + request.getViaPort()); | 535 | cameraInfoDTO.setHostAddress(request.getViaHost() + ":" + request.getViaPort()); |
536 | + cameraInfoDTO.setMediaServerId(mediaConfig.getMediaServerId()); | ||
518 | byte[] cameraMsgBytes = encodingService.encode(cameraInfoDTO); | 537 | byte[] cameraMsgBytes = encodingService.encode(cameraInfoDTO); |
519 | msgBuilder.setContext(ByteString.copyFrom(cameraMsgBytes)); | 538 | msgBuilder.setContext(ByteString.copyFrom(cameraMsgBytes)); |
520 | break; | 539 | break; |
521 | case Catalog: | 540 | case Catalog: |
522 | List<VideoChanelDTO> channelDTO = TKXmlUtil.channelInfoBuilder(devSession, rootElement); | 541 | List<VideoChanelDTO> channelDTO = TKXmlUtil.channelInfoBuilder(devSession, rootElement); |
523 | String cameraCode = devSession.getCameraCode(); | 542 | String cameraCode = devSession.getCameraCode(); |
524 | - int channelNum =1; | ||
525 | - if(!channelDTO.isEmpty()){ | ||
526 | - channelNum = channelDTO.get(0).getSumNum(); | ||
527 | - List<VideoChanelDTO> itemChanel = new ArrayList<>(); | ||
528 | - if(deviceNewChanel.containsKey(cameraCode)){ | ||
529 | - itemChanel =deviceNewChanel.get(cameraCode); | ||
530 | - }else{ | ||
531 | - deviceNewChanel.put(cameraCode,itemChanel); | ||
532 | - } | ||
533 | - itemChanel.addAll(channelDTO); | ||
534 | - } | ||
535 | - if(channelNum == deviceNewChanel.get(cameraCode).size()){ | 543 | + int channelNum = 1; |
544 | + if (!channelDTO.isEmpty()) { | ||
545 | + channelNum = channelDTO.get(0).getSumNum(); | ||
546 | + List<VideoChanelDTO> itemChanel = new ArrayList<>(); | ||
547 | + if (deviceNewChanel.containsKey(cameraCode)) { | ||
548 | + itemChanel = deviceNewChanel.get(cameraCode); | ||
549 | + } else { | ||
550 | + deviceNewChanel.put(cameraCode, itemChanel); | ||
551 | + } | ||
552 | + itemChanel.addAll(channelDTO); | ||
553 | + } | ||
554 | + if (channelNum == deviceNewChanel.get(cameraCode).size()) { | ||
536 | byte[] channaelMsgBytes = encodingService.encode(deviceNewChanel.get(cameraCode)); | 555 | byte[] channaelMsgBytes = encodingService.encode(deviceNewChanel.get(cameraCode)); |
537 | msgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes)); | 556 | msgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes)); |
538 | deviceNewChanel.remove(cameraCode); | 557 | deviceNewChanel.remove(cameraCode); |
@@ -644,7 +663,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -644,7 +663,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
644 | return; | 663 | return; |
645 | } | 664 | } |
646 | DeviceProfile profile = msg.getDeviceProfile(); | 665 | DeviceProfile profile = msg.getDeviceProfile(); |
647 | - if(profile.getTransportType() != DeviceTransportType.GBT28181){ | 666 | + if (profile.getTransportType() != DeviceTransportType.GBT28181) { |
648 | return; | 667 | return; |
649 | } | 668 | } |
650 | GbtDeviceSessionCtx deviceSessionCtx = | 669 | GbtDeviceSessionCtx deviceSessionCtx = |
@@ -698,12 +717,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -698,12 +717,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
698 | .build(); | 717 | .build(); |
699 | commanderService.queryDeviceInfo(deviceSessionCtx, deviceInfoHeader); | 718 | commanderService.queryDeviceInfo(deviceSessionCtx, deviceInfoHeader); |
700 | int sn = (int) ((Math.random() * 9 + 1) * 100000); | 719 | int sn = (int) ((Math.random() * 9 + 1) * 100000); |
701 | - rpcCameraChannel(deviceSessionCtx,sn); | 720 | + rpcCameraChannel(deviceSessionCtx, sn); |
702 | } catch (InvalidArgumentException | SipException | ParseException e) { | 721 | } catch (InvalidArgumentException | SipException | ParseException e) { |
703 | throw new RuntimeException(e); | 722 | throw new RuntimeException(e); |
704 | } | 723 | } |
705 | 724 | ||
706 | - // transportService.getCallbackExecutor().execute(() -> | 725 | + // transportService.getCallbackExecutor().execute(() -> |
707 | // processQueueMessage(ctx)); //this callback will execute in Producer worker thread and | 726 | // processQueueMessage(ctx)); //this callback will execute in Producer worker thread and |
708 | // hard or blocking work have to be submitted to the separate thread. | 727 | // hard or blocking work have to be submitted to the separate thread. |
709 | } | 728 | } |
@@ -735,9 +754,6 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -735,9 +754,6 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
735 | // sipSender.transmitRequest(hostAddress, finalResponse); | 754 | // sipSender.transmitRequest(hostAddress, finalResponse); |
736 | } | 755 | } |
737 | 756 | ||
738 | - | ||
739 | - | ||
740 | - | ||
741 | /** | 757 | /** |
742 | * 向超时订阅发送消息 | 758 | * 向超时订阅发送消息 |
743 | * | 759 | * |
@@ -792,10 +808,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -792,10 +808,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
792 | 808 | ||
793 | String channelId = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.CHANNEL_ID); | 809 | String channelId = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.CHANNEL_ID); |
794 | 810 | ||
795 | - switch (VideoMethodEnum.valueOf(methodType)){ | 811 | + switch (VideoMethodEnum.valueOf(methodType)) { |
796 | case BYE: | 812 | case BYE: |
797 | - SipMessageHeaderDTO messageHeaderDTO = JacksonUtil.convertValue(rpcBody.get(FastIotConstants.ZLMediaBody.MSG_HEADER),SipMessageHeaderDTO.class); | ||
798 | - commanderService.streamByeCmd(devSession,messageHeaderDTO,channelId); | 813 | + SipMessageHeaderDTO messageHeaderDTO = |
814 | + JacksonUtil.convertValue( | ||
815 | + rpcBody.get(FastIotConstants.ZLMediaBody.MSG_HEADER), SipMessageHeaderDTO.class); | ||
816 | + commanderService.streamByeCmd(devSession, messageHeaderDTO, channelId); | ||
799 | break; | 817 | break; |
800 | case INVITE: | 818 | case INVITE: |
801 | JsonNode mediaInform = rpcBody.get(FastIotConstants.ZLMediaBody.MEDIA); | 819 | JsonNode mediaInform = rpcBody.get(FastIotConstants.ZLMediaBody.MEDIA); |
@@ -807,64 +825,81 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -807,64 +825,81 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
807 | String stream = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.SSRCINFO_STREAM); | 825 | String stream = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.SSRCINFO_STREAM); |
808 | 826 | ||
809 | ObjectNode responseJson = JacksonUtil.newObjectNode(); | 827 | ObjectNode responseJson = JacksonUtil.newObjectNode(); |
810 | - responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM,stream); | ||
811 | - responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_PORT,ssrcPort); | ||
812 | - responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_SSRC,ssrc); | ||
813 | - responseJson.set(FastIotConstants.ZLMediaBody.MEDIA,mediaInform); | ||
814 | - responseJson.put(FastIotConstants.ZLMediaBody.CAMERA_CODE,cameraCode); | ||
815 | - | 828 | + responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM, stream); |
829 | + responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_PORT, ssrcPort); | ||
830 | + responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_SSRC, ssrc); | ||
831 | + responseJson.set(FastIotConstants.ZLMediaBody.MEDIA, mediaInform); | ||
832 | + responseJson.put(FastIotConstants.ZLMediaBody.CAMERA_CODE, cameraCode); | ||
816 | 833 | ||
817 | SipMessageHeaderDTO sipMessageHeaderDTO = | 834 | SipMessageHeaderDTO sipMessageHeaderDTO = |
818 | - SipMessageHeaderDTO.builder() | ||
819 | - .viaTag(TKSipUtils.getNewViaTag()) | ||
820 | - .fromTag(TKSipUtils.getNewViaTag()) | ||
821 | - .toTag(null) | ||
822 | - .build(); | 835 | + SipMessageHeaderDTO.builder() |
836 | + .viaTag(TKSipUtils.getNewViaTag()) | ||
837 | + .fromTag(TKSipUtils.getNewViaTag()) | ||
838 | + .toTag(null) | ||
839 | + .build(); | ||
823 | 840 | ||
824 | commanderService.previewStreamCmd( | 841 | commanderService.previewStreamCmd( |
825 | - devSession, sipMessageHeaderDTO, sdpIp, ssrc, ssrcPort, channelId, | ||
826 | - e -> { | ||
827 | - // TODO: 2023/10/13 命令下发失败,需要流媒体处理的业务逻辑 | ||
828 | - | ||
829 | -// responseJson.set(FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(e)); | ||
830 | - String contentString = JacksonUtil.toString(responseJson); | ||
831 | - log.warn("命令下发【失败】,响应给流媒体的数据【{}】",contentString); | ||
832 | - transportService.process(devSession.getSessionInfo(), | ||
833 | - TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | ||
834 | - .setRequestId(rpcRequest.getRequestId()).setError(e.msg).build(), TransportServiceCallback.EMPTY); | ||
835 | - }, | ||
836 | - e -> { | ||
837 | - // TODO: 2023/10/13 命令下发成功,需要流媒体处理的业务逻辑 | ||
838 | - transportService.process(devSession.getSessionInfo(), rpcRequest, RpcStatus.SENT, TransportServiceCallback.EMPTY); | ||
839 | - | ||
840 | - | ||
841 | - responseJson.put(FastIotConstants.ZLMediaBody.CALL_ID,e.callId); | ||
842 | - ResponseEvent responseEvent = (ResponseEvent) e.event; | ||
843 | - SIPResponse response = (SIPResponse) responseEvent.getResponse(); | ||
844 | - SipMessageHeaderDTO sipMessage = | ||
845 | - SipMessageHeaderDTO.builder() | ||
846 | - .callId(response.getCallIdHeader().getCallId()) | ||
847 | - .fromTag(response.getFromTag()) | ||
848 | - .toTag(response.getToTag()) | ||
849 | - .viaBranch(response.getTopmostViaHeader().getBranch()) | ||
850 | - .build(); | ||
851 | - responseJson.set(FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(sipMessage)); | ||
852 | - String contentString = new String(responseEvent.getResponse().getRawContent()); | ||
853 | - responseJson.put(FastIotConstants.ZLMediaBody.MSG_CONTEXT, contentString); | ||
854 | - responseJson.put(FastIotConstants.ZLMediaBody.SESSION_TYPE,SessionTypeEnum.PLAY.name()); | ||
855 | - responseJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID,channelId); | ||
856 | - responseJson.put(FastIotConstants.ZLMediaBody.SSRC_CHECK,devSession.isSsrcCheck()); | ||
857 | - String responseStr = JacksonUtil.toString(responseJson); | ||
858 | - log.warn("命令下发【成功】,CallId是否一致【{}】,响应给流媒体的数据【{}】",e.callId.equals(response.getCallIdHeader().getCallId()),responseStr); | ||
859 | - TransportProtos.ToDeviceRpcResponseMsg.Builder builder = TransportProtos.ToDeviceRpcResponseMsg.newBuilder(); | ||
860 | - builder.setRequestId(rpcRequest.getRequestId()).setPayload(responseStr); | ||
861 | - transportService.process(devSession.getSessionInfo(), | ||
862 | - builder.build(), TransportServiceCallback.EMPTY); | ||
863 | - | ||
864 | - }); | 842 | + devSession, |
843 | + sipMessageHeaderDTO, | ||
844 | + sdpIp, | ||
845 | + ssrc, | ||
846 | + ssrcPort, | ||
847 | + channelId, | ||
848 | + e -> { | ||
849 | + // TODO: 2023/10/13 命令下发失败,需要流媒体处理的业务逻辑 | ||
850 | + | ||
851 | + // responseJson.set(FastIotConstants.ZLMediaBody.MSG_HEADER, | ||
852 | + // JacksonUtil.valueToTree(e)); | ||
853 | + String contentString = JacksonUtil.toString(responseJson); | ||
854 | + log.warn("命令下发【失败】,响应给流媒体的数据【{}】", contentString); | ||
855 | + transportService.process( | ||
856 | + devSession.getSessionInfo(), | ||
857 | + TransportProtos.ToDeviceRpcResponseMsg.newBuilder() | ||
858 | + .setRequestId(rpcRequest.getRequestId()) | ||
859 | + .setError(e.msg) | ||
860 | + .build(), | ||
861 | + TransportServiceCallback.EMPTY); | ||
862 | + }, | ||
863 | + e -> { | ||
864 | + // TODO: 2023/10/13 命令下发成功,需要流媒体处理的业务逻辑 | ||
865 | + transportService.process( | ||
866 | + devSession.getSessionInfo(), | ||
867 | + rpcRequest, | ||
868 | + RpcStatus.SENT, | ||
869 | + TransportServiceCallback.EMPTY); | ||
870 | + | ||
871 | + responseJson.put(FastIotConstants.ZLMediaBody.CALL_ID, e.callId); | ||
872 | + ResponseEvent responseEvent = (ResponseEvent) e.event; | ||
873 | + SIPResponse response = (SIPResponse) responseEvent.getResponse(); | ||
874 | + SipMessageHeaderDTO sipMessage = | ||
875 | + SipMessageHeaderDTO.builder() | ||
876 | + .callId(response.getCallIdHeader().getCallId()) | ||
877 | + .fromTag(response.getFromTag()) | ||
878 | + .toTag(response.getToTag()) | ||
879 | + .viaBranch(response.getTopmostViaHeader().getBranch()) | ||
880 | + .build(); | ||
881 | + responseJson.set( | ||
882 | + FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(sipMessage)); | ||
883 | + String contentString = new String(responseEvent.getResponse().getRawContent()); | ||
884 | + responseJson.put(FastIotConstants.ZLMediaBody.MSG_CONTEXT, contentString); | ||
885 | + responseJson.put( | ||
886 | + FastIotConstants.ZLMediaBody.SESSION_TYPE, SessionTypeEnum.PLAY.name()); | ||
887 | + responseJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, channelId); | ||
888 | + responseJson.put(FastIotConstants.ZLMediaBody.SSRC_CHECK, devSession.isSsrcCheck()); | ||
889 | + String responseStr = JacksonUtil.toString(responseJson); | ||
890 | + log.warn( | ||
891 | + "命令下发【成功】,CallId是否一致【{}】,响应给流媒体的数据【{}】", | ||
892 | + e.callId.equals(response.getCallIdHeader().getCallId()), | ||
893 | + responseStr); | ||
894 | + TransportProtos.ToDeviceRpcResponseMsg.Builder builder = | ||
895 | + TransportProtos.ToDeviceRpcResponseMsg.newBuilder(); | ||
896 | + builder.setRequestId(rpcRequest.getRequestId()).setPayload(responseStr); | ||
897 | + transportService.process( | ||
898 | + devSession.getSessionInfo(), builder.build(), TransportServiceCallback.EMPTY); | ||
899 | + }); | ||
865 | break; | 900 | break; |
866 | case MESSAGE: | 901 | case MESSAGE: |
867 | - toDeviceRpcMessage(devSession,channelId,rpcBody); | 902 | + toDeviceRpcMessage(devSession, channelId, rpcBody); |
868 | break; | 903 | break; |
869 | } | 904 | } |
870 | } catch (InvalidArgumentException | SipException | ParseException e) { | 905 | } catch (InvalidArgumentException | SipException | ParseException e) { |
@@ -873,47 +908,54 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | @@ -873,47 +908,54 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent | ||
873 | } | 908 | } |
874 | } | 909 | } |
875 | 910 | ||
876 | - private void toDeviceRpcMessage(GbtDeviceSessionCtx devSession,String channelId,JsonNode rpcBody) throws InvalidArgumentException, ParseException, SipException { | 911 | + private void toDeviceRpcMessage( |
912 | + GbtDeviceSessionCtx devSession, String channelId, JsonNode rpcBody) | ||
913 | + throws InvalidArgumentException, ParseException, SipException { | ||
877 | SipMessageHeaderDTO controlHeaderDTO = | 914 | SipMessageHeaderDTO controlHeaderDTO = |
878 | - SipMessageHeaderDTO.builder() | ||
879 | - .viaTag(TKSipUtils.getNewViaTag()) | ||
880 | - .fromTag(TKSipUtils.getNewViaTag()) | ||
881 | - .toTag(null) | ||
882 | - .build(); | 915 | + SipMessageHeaderDTO.builder() |
916 | + .viaTag(TKSipUtils.getNewViaTag()) | ||
917 | + .fromTag(TKSipUtils.getNewViaTag()) | ||
918 | + .toTag(null) | ||
919 | + .build(); | ||
883 | String msgType = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_TYPE).asText(); | 920 | String msgType = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_TYPE).asText(); |
884 | - switch (VideoXmlEnum.valueOf(msgType)){ | 921 | + switch (VideoXmlEnum.valueOf(msgType)) { |
885 | case Control: | 922 | case Control: |
886 | - PTZCmdDTO ptzCmdDTO = JacksonUtil.convertValue(rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT),PTZCmdDTO.class); | ||
887 | - commanderService.controlPtzCmd(channelId,devSession,controlHeaderDTO,ptzCmdDTO); | 923 | + PTZCmdDTO ptzCmdDTO = |
924 | + JacksonUtil.convertValue( | ||
925 | + rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT), PTZCmdDTO.class); | ||
926 | + commanderService.controlPtzCmd(channelId, devSession, controlHeaderDTO, ptzCmdDTO); | ||
888 | break; | 927 | break; |
889 | case Query: | 928 | case Query: |
890 | int sn = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT).intValue(); | 929 | int sn = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT).intValue(); |
891 | - rpcCameraChannel(devSession,sn); | 930 | + rpcCameraChannel(devSession, sn); |
892 | } | 931 | } |
893 | } | 932 | } |
894 | 933 | ||
895 | /** | 934 | /** |
896 | * 查询设备通道信息 | 935 | * 查询设备通道信息 |
936 | + * | ||
897 | * @throws InvalidArgumentException | 937 | * @throws InvalidArgumentException |
898 | * @throws SipException | 938 | * @throws SipException |
899 | * @throws ParseException | 939 | * @throws ParseException |
900 | */ | 940 | */ |
901 | - private void rpcCameraChannel(GbtDeviceSessionCtx deviceSessionCtx,int sn) throws InvalidArgumentException, SipException, ParseException { | 941 | + private void rpcCameraChannel(GbtDeviceSessionCtx deviceSessionCtx, int sn) |
942 | + throws InvalidArgumentException, SipException, ParseException { | ||
902 | SipMessageHeaderDTO catalogHeader = | 943 | SipMessageHeaderDTO catalogHeader = |
903 | - SipMessageHeaderDTO.builder() | ||
904 | - .viaTag(TKSipUtils.getNewViaTag()) | ||
905 | - .fromTag(TKSipUtils.getNewFromTag()) | ||
906 | - .build(); | 944 | + SipMessageHeaderDTO.builder() |
945 | + .viaTag(TKSipUtils.getNewViaTag()) | ||
946 | + .fromTag(TKSipUtils.getNewFromTag()) | ||
947 | + .build(); | ||
907 | commanderService.queryCatalog( | 948 | commanderService.queryCatalog( |
908 | - deviceSessionCtx, | ||
909 | - catalogHeader, | ||
910 | - sn, | ||
911 | - ev -> { | ||
912 | - String errorMsg = String.format("同步通道失败,错误码: %s, %s", ev.statusCode, ev.msg); | ||
913 | - // catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), | ||
914 | - // errorMsg); | ||
915 | - }); | 949 | + deviceSessionCtx, |
950 | + catalogHeader, | ||
951 | + sn, | ||
952 | + ev -> { | ||
953 | + String errorMsg = String.format("同步通道失败,错误码: %s, %s", ev.statusCode, ev.msg); | ||
954 | + // catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), | ||
955 | + // errorMsg); | ||
956 | + }); | ||
916 | } | 957 | } |
958 | + | ||
917 | private String rpcParamVal(JsonNode rpcBody, String key) { | 959 | private String rpcParamVal(JsonNode rpcBody, String key) { |
918 | if (rpcBody.has(key)) { | 960 | if (rpcBody.has(key)) { |
919 | return rpcBody.get(key).asText(); | 961 | return rpcBody.get(key).asText(); |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/SIPProvider.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/SIPProvider.java
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/SIPRequestProcessorParent.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/SIPRequestProcessorParent.java
1 | -package org.thingsboard.server.transport.gbt28181; | 1 | +package org.thingsboard.server.transport.gbt28181.sip.processor; |
2 | 2 | ||
3 | import gov.nist.javax.sip.message.SIPRequest; | 3 | import gov.nist.javax.sip.message.SIPRequest; |
4 | import gov.nist.javax.sip.message.SIPResponse; | 4 | import gov.nist.javax.sip.message.SIPResponse; |
@@ -20,7 +20,7 @@ import org.dom4j.DocumentException; | @@ -20,7 +20,7 @@ import org.dom4j.DocumentException; | ||
20 | import org.dom4j.Element; | 20 | import org.dom4j.Element; |
21 | import org.dom4j.io.SAXReader; | 21 | import org.dom4j.io.SAXReader; |
22 | import org.springframework.beans.factory.annotation.Autowired; | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | -import org.thingsboard.server.transport.SIPSender; | 23 | +import org.thingsboard.server.transport.cmd.SIPSender; |
24 | import org.thingsboard.server.transport.util.TKSipUtils; | 24 | import org.thingsboard.server.transport.util.TKSipUtils; |
25 | 25 | ||
26 | /** 处理接收IPCamera发来的SIP协议请求消息 */ | 26 | /** 处理接收IPCamera发来的SIP协议请求消息 */ |
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/TimeoutProcessorImpl.java
renamed from
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/process/timeout/TimeoutProcessorImpl.java
1 | -package org.thingsboard.server.transport.process.timeout; | 1 | +package org.thingsboard.server.transport.gbt28181.sip.processor; |
2 | 2 | ||
3 | import javax.sip.TimeoutEvent; | 3 | import javax.sip.TimeoutEvent; |
4 | import javax.sip.header.CallIdHeader; | 4 | import javax.sip.header.CallIdHeader; |
@@ -8,8 +8,6 @@ import org.springframework.beans.factory.InitializingBean; | @@ -8,8 +8,6 @@ import org.springframework.beans.factory.InitializingBean; | ||
8 | import org.springframework.beans.factory.annotation.Autowired; | 8 | import org.springframework.beans.factory.annotation.Autowired; |
9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
10 | import org.springframework.stereotype.Component; | 10 | import org.springframework.stereotype.Component; |
11 | -import org.thingsboard.server.transport.gbt28181.ITimeoutProcessor; | ||
12 | -import org.thingsboard.server.transport.SIPProcessorObserver; | ||
13 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; | 11 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; |
14 | 12 | ||
15 | @Component | 13 | @Component |
1 | +package org.thingsboard.server.transport.gbt28181.zlm; | ||
2 | + | ||
3 | +import com.google.protobuf.ByteString; | ||
4 | +import java.net.InetAddress; | ||
5 | +import java.net.UnknownHostException; | ||
6 | +import java.util.List; | ||
7 | +import lombok.Getter; | ||
8 | +import lombok.RequiredArgsConstructor; | ||
9 | +import lombok.extern.slf4j.Slf4j; | ||
10 | +import org.springframework.beans.factory.annotation.Value; | ||
11 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | ||
12 | +import org.springframework.boot.context.event.ApplicationReadyEvent; | ||
13 | +import org.springframework.context.event.EventListener; | ||
14 | +import org.springframework.core.annotation.Order; | ||
15 | +import org.springframework.stereotype.Component; | ||
16 | +import org.thingsboard.common.util.JacksonUtil; | ||
17 | +import org.thingsboard.server.common.data.StringUtils; | ||
18 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | ||
19 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | ||
20 | +import org.thingsboard.server.common.data.yunteng.utils.DataUtils; | ||
21 | +import org.thingsboard.server.common.transport.TransportService; | ||
22 | +import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; | ||
23 | +import org.thingsboard.server.gen.transport.TransportProtos; | ||
24 | +import org.thingsboard.server.transport.config.MediaConfig; | ||
25 | +import org.thingsboard.server.transport.config.SipConfig; | ||
26 | + | ||
27 | +@Component() | ||
28 | +@Slf4j | ||
29 | +@RequiredArgsConstructor | ||
30 | +@ConditionalOnExpression( | ||
31 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | ||
32 | +public class ZLMediaKitStateRunner { | ||
33 | + private final MediaConfig mediaConfig; | ||
34 | + private final SipConfig sipConfig; | ||
35 | + private final DataDecodingEncodingService encodingService; | ||
36 | + private final CacheUtils cacheUtils; | ||
37 | + | ||
38 | + @Value("${transport.gbt28181.media.defaultStateCheckIntervalInSec}") | ||
39 | + @Getter | ||
40 | + private int defaultStateCheckIntervalInSec; | ||
41 | + | ||
42 | + private final TransportService transportService; | ||
43 | + | ||
44 | + @EventListener(ApplicationReadyEvent.class) | ||
45 | + @Order(value = 3) | ||
46 | + public void init(ApplicationReadyEvent applicationReadyEvent) throws UnknownHostException { | ||
47 | + TransportProtos.Gbt28181MediaServerMsg.Builder msgBuilder = | ||
48 | + TransportProtos.Gbt28181MediaServerMsg.newBuilder(); | ||
49 | + cacheUtils.put( | ||
50 | + FastIotConstants.CacheSipKey.TK_SIP_CACHE_NAME, | ||
51 | + mediaConfig.getMediaServerId(), | ||
52 | + sipConfig.getDomain()); | ||
53 | + if (StringUtils.isEmpty(mediaConfig.getHookIp())) { | ||
54 | + mediaConfig.setHookIp(sipConfig.getIp().split(",")[0]); | ||
55 | + } | ||
56 | + if (StringUtils.isEmpty(mediaConfig.getStreamIp())) { | ||
57 | + mediaConfig.setStreamIp(mediaConfig.getIp()); | ||
58 | + } | ||
59 | + String sdpIp = mediaConfig.getSdpIp(); | ||
60 | + if (StringUtils.isEmpty(sdpIp)) { | ||
61 | + sdpIp = mediaConfig.getIp(); | ||
62 | + } else if (!DataUtils.isIPAddress(sdpIp)) { | ||
63 | + sdpIp = InetAddress.getByName(sdpIp).getHostAddress(); | ||
64 | + } | ||
65 | + mediaConfig.setSdpIp(sdpIp); | ||
66 | + byte[] mediaMsgBytes = encodingService.encode(JacksonUtil.valueToTree(mediaConfig)); | ||
67 | + msgBuilder.setProfile(ByteString.copyFrom(mediaMsgBytes)); | ||
68 | + // 从数据库获取所有的流媒体信息 | ||
69 | + List<TransportProtos.Gbt28181MediaServerMsg> dtoList = | ||
70 | + transportService.freshGtb28181Media(msgBuilder.build()); | ||
71 | + } | ||
72 | +} |
@@ -13,9 +13,7 @@ import lombok.Getter; | @@ -13,9 +13,7 @@ import lombok.Getter; | ||
13 | import lombok.Setter; | 13 | import lombok.Setter; |
14 | import lombok.extern.slf4j.Slf4j; | 14 | import lombok.extern.slf4j.Slf4j; |
15 | import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; | 15 | import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; |
16 | -import org.thingsboard.server.transport.GbtTransportContext; | ||
17 | - | ||
18 | -import javax.sip.RequestEvent; | 16 | +import org.thingsboard.server.transport.gbt28181.session.GbtTransportContext; |
19 | 17 | ||
20 | /** | 18 | /** |
21 | * @author Andrew Shvayka | 19 | * @author Andrew Shvayka |
@@ -10,10 +10,10 @@ import javax.sip.SipFactory; | @@ -10,10 +10,10 @@ import javax.sip.SipFactory; | ||
10 | import javax.sip.header.UserAgentHeader; | 10 | import javax.sip.header.UserAgentHeader; |
11 | import org.apache.commons.lang3.RandomStringUtils; | 11 | import org.apache.commons.lang3.RandomStringUtils; |
12 | import org.springframework.util.ObjectUtils; | 12 | import org.springframework.util.ObjectUtils; |
13 | -import org.thingsboard.server.common.data.yunteng.config.media.ThingsKitVersionConfig; | ||
14 | import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; | 13 | import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; |
15 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; | 14 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; |
16 | -import org.thingsboard.server.transport.info.RemoteAddressInfo; | 15 | +import org.thingsboard.server.transport.config.ThingsKitVersionConfig; |
16 | +import org.thingsboard.server.transport.gbt28181.auth.RemoteAddressInfo; | ||
17 | 17 | ||
18 | public class TKSipUtils { | 18 | public class TKSipUtils { |
19 | public static String getNewMessageViaBranchTag() { | 19 | public static String getNewMessageViaBranchTag() { |
@@ -55,14 +55,14 @@ public class TKSipUtils { | @@ -55,14 +55,14 @@ public class TKSipUtils { | ||
55 | builder.append(strTmp, 0, 2); | 55 | builder.append(strTmp, 0, 2); |
56 | strTmp = String.format("%X", combineCode2); | 56 | strTmp = String.format("%X", combineCode2); |
57 | builder.append(strTmp, 0, 1).append("0"); | 57 | builder.append(strTmp, 0, 1).append("0"); |
58 | - //计算校验码 | ||
59 | - int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100; | 58 | + // 计算校验码 |
59 | + int checkCode = | ||
60 | + (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100; | ||
60 | strTmp = String.format("%02X", checkCode); | 61 | strTmp = String.format("%02X", checkCode); |
61 | builder.append(strTmp, 0, 2); | 62 | builder.append(strTmp, 0, 2); |
62 | return builder.toString(); | 63 | return builder.toString(); |
63 | } | 64 | } |
64 | 65 | ||
65 | - | ||
66 | public static UserAgentHeader createUserAgentHeader(ThingsKitVersionConfig config) | 66 | public static UserAgentHeader createUserAgentHeader(ThingsKitVersionConfig config) |
67 | throws PeerUnavailableException, ParseException { | 67 | throws PeerUnavailableException, ParseException { |
68 | List<String> agentParam = new ArrayList<>(); | 68 | List<String> agentParam = new ArrayList<>(); |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2022 The Thingsboard Authors | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | * | 3 | * |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | 4 | + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
5 | + * except in compliance with the License. You may obtain a copy of the License at | ||
7 | * | 6 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | 7 | + * <p>http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | 8 | * |
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | 9 | + * <p>Unless required by applicable law or agreed to in writing, software distributed under the |
10 | + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
11 | + * express or implied. See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | 12 | * limitations under the License. |
15 | */ | 13 | */ |
16 | package org.thingsboard.server.common.transport; | 14 | package org.thingsboard.server.common.transport; |
17 | 15 | ||
16 | +import java.util.List; | ||
17 | +import java.util.concurrent.ExecutorService; | ||
18 | +import java.util.concurrent.atomic.AtomicInteger; | ||
18 | import org.thingsboard.server.common.data.DeviceProfile; | 19 | import org.thingsboard.server.common.data.DeviceProfile; |
19 | import org.thingsboard.server.common.data.DeviceTransportType; | 20 | import org.thingsboard.server.common.data.DeviceTransportType; |
20 | import org.thingsboard.server.common.data.rpc.RpcStatus; | 21 | import org.thingsboard.server.common.data.rpc.RpcStatus; |
@@ -40,10 +41,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRespon | @@ -40,10 +41,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRespon | ||
40 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; | 41 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; |
41 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; | 42 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; |
42 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; | 43 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
43 | -import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; | ||
44 | import org.thingsboard.server.gen.transport.TransportProtos.PostEventMsg; | 44 | import org.thingsboard.server.gen.transport.TransportProtos.PostEventMsg; |
45 | +import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; | ||
45 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; | 46 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
46 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; | 47 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
48 | +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | ||
47 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg; | 49 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg; |
48 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; | 50 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
49 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; | 51 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; |
@@ -57,104 +59,140 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre | @@ -57,104 +59,140 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre | ||
57 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; | 59 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; |
58 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; | 60 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; |
59 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; | 61 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; |
60 | -import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | ||
61 | 62 | ||
62 | -import java.util.List; | ||
63 | -import java.util.concurrent.ExecutorService; | ||
64 | -import java.util.concurrent.atomic.AtomicInteger; | ||
65 | - | ||
66 | -/** | ||
67 | - * Created by ashvayka on 04.10.18. | ||
68 | - */ | 63 | +/** Created by ashvayka on 04.10.18. */ |
69 | public interface TransportService { | 64 | public interface TransportService { |
70 | 65 | ||
71 | - GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg); | ||
72 | - | ||
73 | - GetResourceResponseMsg getResource(GetResourceRequestMsg msg); | ||
74 | - | ||
75 | - GetSnmpDevicesResponseMsg getSnmpDevicesIds(GetSnmpDevicesRequestMsg requestMsg); | ||
76 | - | ||
77 | - GetDeviceResponseMsg getDevice(GetDeviceRequestMsg requestMsg); | ||
78 | - | ||
79 | - GetDeviceCredentialsResponseMsg getDeviceCredentials(GetDeviceCredentialsRequestMsg requestMsg); | 66 | + GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg); |
80 | 67 | ||
68 | + GetResourceResponseMsg getResource(GetResourceRequestMsg msg); | ||
81 | 69 | ||
70 | + GetSnmpDevicesResponseMsg getSnmpDevicesIds(GetSnmpDevicesRequestMsg requestMsg); | ||
82 | 71 | ||
83 | - void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg, | ||
84 | - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | 72 | + GetDeviceResponseMsg getDevice(GetDeviceRequestMsg requestMsg); |
85 | 73 | ||
86 | - void process(DeviceTransportType transportType, ValidateBasicMqttCredRequestMsg msg, | ||
87 | - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | 74 | + GetDeviceCredentialsResponseMsg getDeviceCredentials(GetDeviceCredentialsRequestMsg requestMsg); |
88 | 75 | ||
89 | - void process(DeviceTransportType transportType, ValidateDeviceX509CertRequestMsg msg, | ||
90 | - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | 76 | + void process( |
77 | + DeviceTransportType transportType, | ||
78 | + ValidateDeviceTokenRequestMsg msg, | ||
79 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | ||
91 | 80 | ||
92 | - void process(ValidateDeviceLwM2MCredentialsRequestMsg msg, | ||
93 | - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | 81 | + void process( |
82 | + DeviceTransportType transportType, | ||
83 | + ValidateBasicMqttCredRequestMsg msg, | ||
84 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | ||
94 | 85 | ||
95 | - void process(GetOrCreateDeviceFromGatewayRequestMsg msg, | ||
96 | - TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback); | 86 | + void process( |
87 | + DeviceTransportType transportType, | ||
88 | + ValidateDeviceX509CertRequestMsg msg, | ||
89 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | ||
97 | 90 | ||
98 | - void process(ProvisionDeviceRequestMsg msg, | ||
99 | - TransportServiceCallback<ProvisionDeviceResponseMsg> callback); | 91 | + void process( |
92 | + ValidateDeviceLwM2MCredentialsRequestMsg msg, | ||
93 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); | ||
100 | 94 | ||
101 | - void onProfileUpdate(DeviceProfile deviceProfile); | 95 | + void process( |
96 | + GetOrCreateDeviceFromGatewayRequestMsg msg, | ||
97 | + TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback); | ||
102 | 98 | ||
103 | - void process(LwM2MRequestMsg msg, | ||
104 | - TransportServiceCallback<LwM2MResponseMsg> callback); | 99 | + void process( |
100 | + ProvisionDeviceRequestMsg msg, TransportServiceCallback<ProvisionDeviceResponseMsg> callback); | ||
105 | 101 | ||
106 | - void process(SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback<Void> callback); | 102 | + void onProfileUpdate(DeviceProfile deviceProfile); |
107 | 103 | ||
108 | - void process(SessionInfoProto sessionInfo, PostTelemetryMsg msg, TransportServiceCallback<Void> callback); | 104 | + void process(LwM2MRequestMsg msg, TransportServiceCallback<LwM2MResponseMsg> callback); |
109 | 105 | ||
110 | - void process(SessionInfoProto sessionInfo, PostAttributeMsg msg, TransportServiceCallback<Void> callback); | 106 | + void process( |
107 | + SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback<Void> callback); | ||
111 | 108 | ||
109 | + void process( | ||
110 | + SessionInfoProto sessionInfo, PostTelemetryMsg msg, TransportServiceCallback<Void> callback); | ||
112 | 111 | ||
113 | - void process(SessionInfoProto sessionInfo, GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback); | 112 | + void process( |
113 | + SessionInfoProto sessionInfo, PostAttributeMsg msg, TransportServiceCallback<Void> callback); | ||
114 | 114 | ||
115 | - void process(SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback); | 115 | + void process( |
116 | + SessionInfoProto sessionInfo, | ||
117 | + GetAttributeRequestMsg msg, | ||
118 | + TransportServiceCallback<Void> callback); | ||
116 | 119 | ||
117 | - void process(SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback); | 120 | + void process( |
121 | + SessionInfoProto sessionInfo, | ||
122 | + SubscribeToAttributeUpdatesMsg msg, | ||
123 | + TransportServiceCallback<Void> callback); | ||
118 | 124 | ||
119 | - void process(SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback); | 125 | + void process( |
126 | + SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback); | ||
120 | 127 | ||
121 | - void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback); | 128 | + void process( |
129 | + SessionInfoProto sessionInfo, | ||
130 | + ToDeviceRpcResponseMsg msg, | ||
131 | + TransportServiceCallback<Void> callback); | ||
122 | 132 | ||
123 | - void process(SessionInfoProto sessionInfo, ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback); | 133 | + void process( |
134 | + SessionInfoProto sessionInfo, | ||
135 | + ToServerRpcRequestMsg msg, | ||
136 | + TransportServiceCallback<Void> callback); | ||
124 | 137 | ||
125 | - void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback); | 138 | + void process( |
139 | + SessionInfoProto sessionInfo, | ||
140 | + ToDeviceRpcRequestMsg msg, | ||
141 | + RpcStatus rpcStatus, | ||
142 | + TransportServiceCallback<Void> callback); | ||
126 | 143 | ||
127 | - void process(SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> callback); | 144 | + void process( |
145 | + SessionInfoProto sessionInfo, | ||
146 | + SubscriptionInfoProto msg, | ||
147 | + TransportServiceCallback<Void> callback); | ||
128 | 148 | ||
129 | - void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback); | 149 | + void process( |
150 | + SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> callback); | ||
130 | 151 | ||
131 | - void process(SessionInfoProto sessionInfoProto, GetOtaPackageRequestMsg msg, TransportServiceCallback<GetOtaPackageResponseMsg> callback); | 152 | + void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback); |
132 | 153 | ||
133 | - SessionMetaData registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener); | 154 | + void process( |
155 | + SessionInfoProto sessionInfoProto, | ||
156 | + GetOtaPackageRequestMsg msg, | ||
157 | + TransportServiceCallback<GetOtaPackageResponseMsg> callback); | ||
134 | 158 | ||
135 | - SessionMetaData registerSyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout); | 159 | + SessionMetaData registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener); |
136 | 160 | ||
137 | - void reportActivity(SessionInfoProto sessionInfo); | 161 | + SessionMetaData registerSyncSession( |
162 | + SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout); | ||
138 | 163 | ||
139 | - void deregisterSession(SessionInfoProto sessionInfo); | 164 | + void reportActivity(SessionInfoProto sessionInfo); |
140 | 165 | ||
141 | - void log(SessionInfoProto sessionInfo, String msg); | 166 | + void deregisterSession(SessionInfoProto sessionInfo); |
142 | 167 | ||
143 | - void notifyAboutUplink(SessionInfoProto sessionInfo, TransportProtos.UplinkNotificationMsg build, TransportServiceCallback<Void> empty); | 168 | + void log(SessionInfoProto sessionInfo, String msg); |
144 | 169 | ||
145 | - ExecutorService getCallbackExecutor(); | 170 | + void notifyAboutUplink( |
171 | + SessionInfoProto sessionInfo, | ||
172 | + TransportProtos.UplinkNotificationMsg build, | ||
173 | + TransportServiceCallback<Void> empty); | ||
146 | 174 | ||
147 | - boolean hasSession(SessionInfoProto sessionInfo); | 175 | + ExecutorService getCallbackExecutor(); |
148 | 176 | ||
149 | - void createGaugeStats(String openConnections, AtomicInteger connectionsCounter); | 177 | + boolean hasSession(SessionInfoProto sessionInfo); |
150 | 178 | ||
179 | + void createGaugeStats(String openConnections, AtomicInteger connectionsCounter); | ||
151 | 180 | ||
181 | + // Thingskit function:begin | ||
182 | + List<ScriptProto> getScripts(ScriptProto msg); | ||
152 | 183 | ||
184 | + void process( | ||
185 | + SessionInfoProto sessionInfo, | ||
186 | + PostEventMsg msg, | ||
187 | + TransportServiceCallback<Void> callback, | ||
188 | + String topicName); | ||
153 | 189 | ||
190 | + void process( | ||
191 | + SessionInfoProto sessionInfo, | ||
192 | + TransportProtos.Gbt28181RequestMsg msg, | ||
193 | + TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback); | ||
154 | 194 | ||
155 | - //Thingskit function:begin | ||
156 | - List<ScriptProto> getScripts(ScriptProto msg); | ||
157 | - void process(SessionInfoProto sessionInfo, PostEventMsg msg, TransportServiceCallback<Void> callback,String topicName); | ||
158 | - void process(SessionInfoProto sessionInfo, TransportProtos.Gbt28181RequestMsg msg, TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback); | ||
159 | - //Thingskit function:end | 195 | + List<TransportProtos.Gbt28181MediaServerMsg> freshGtb28181Media( |
196 | + TransportProtos.Gbt28181MediaServerMsg msg); | ||
197 | + // Thingskit function:end | ||
160 | } | 198 | } |
1 | /** | 1 | /** |
2 | * Copyright © 2016-2022 The Thingsboard Authors | 2 | * Copyright © 2016-2022 The Thingsboard Authors |
3 | * | 3 | * |
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | 4 | + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file |
5 | + * except in compliance with the License. You may obtain a copy of the License at | ||
7 | * | 6 | * |
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | 7 | + * <p>http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | 8 | * |
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | 9 | + * <p>Unless required by applicable law or agreed to in writing, software distributed under the |
10 | + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
11 | + * express or implied. See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | 12 | * limitations under the License. |
15 | */ | 13 | */ |
16 | package org.thingsboard.server.common.transport.service; | 14 | package org.thingsboard.server.common.transport.service; |
17 | 15 | ||
16 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.EVENT_IDENTIFIER; | ||
17 | + | ||
18 | import com.google.common.util.concurrent.Futures; | 18 | import com.google.common.util.concurrent.Futures; |
19 | import com.google.common.util.concurrent.ListenableFuture; | 19 | import com.google.common.util.concurrent.ListenableFuture; |
20 | import com.google.common.util.concurrent.MoreExecutors; | 20 | import com.google.common.util.concurrent.MoreExecutors; |
21 | import com.google.gson.Gson; | 21 | import com.google.gson.Gson; |
22 | import com.google.gson.JsonObject; | 22 | import com.google.gson.JsonObject; |
23 | import com.google.protobuf.ByteString; | 23 | import com.google.protobuf.ByteString; |
24 | +import java.util.Collections; | ||
25 | +import java.util.HashSet; | ||
26 | +import java.util.LinkedHashMap; | ||
27 | +import java.util.List; | ||
28 | +import java.util.Map; | ||
29 | +import java.util.Optional; | ||
30 | +import java.util.Random; | ||
31 | +import java.util.Set; | ||
32 | +import java.util.UUID; | ||
33 | +import java.util.concurrent.*; | ||
34 | +import java.util.concurrent.atomic.AtomicInteger; | ||
35 | +import java.util.stream.Collectors; | ||
36 | +import javax.annotation.PostConstruct; | ||
37 | +import javax.annotation.PreDestroy; | ||
24 | import lombok.Getter; | 38 | import lombok.Getter; |
25 | import lombok.extern.slf4j.Slf4j; | 39 | import lombok.extern.slf4j.Slf4j; |
26 | import org.springframework.beans.factory.annotation.Value; | 40 | import org.springframework.beans.factory.annotation.Value; |
27 | import org.springframework.context.ApplicationEventPublisher; | 41 | import org.springframework.context.ApplicationEventPublisher; |
42 | +import org.springframework.core.annotation.Order; | ||
28 | import org.springframework.scheduling.annotation.Scheduled; | 43 | import org.springframework.scheduling.annotation.Scheduled; |
29 | import org.springframework.stereotype.Service; | 44 | import org.springframework.stereotype.Service; |
30 | import org.thingsboard.common.util.ThingsBoardExecutors; | 45 | import org.thingsboard.common.util.ThingsBoardExecutors; |
@@ -79,13 +94,13 @@ import org.thingsboard.server.common.transport.yunteng.ScriptUpdatedEvent; | @@ -79,13 +94,13 @@ import org.thingsboard.server.common.transport.yunteng.ScriptUpdatedEvent; | ||
79 | import org.thingsboard.server.gen.transport.TransportProtos; | 94 | import org.thingsboard.server.gen.transport.TransportProtos; |
80 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; | 95 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
81 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; | 96 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
97 | +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | ||
82 | import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; | 98 | import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
83 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; | 99 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
84 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; | 100 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
85 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; | 101 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
86 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; | 102 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
87 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; | 103 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
88 | -import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | ||
89 | import org.thingsboard.server.queue.TbQueueCallback; | 104 | import org.thingsboard.server.queue.TbQueueCallback; |
90 | import org.thingsboard.server.queue.TbQueueConsumer; | 105 | import org.thingsboard.server.queue.TbQueueConsumer; |
91 | import org.thingsboard.server.queue.TbQueueMsgMetadata; | 106 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
@@ -102,1204 +117,1604 @@ import org.thingsboard.server.queue.usagestats.TbApiUsageClient; | @@ -102,1204 +117,1604 @@ import org.thingsboard.server.queue.usagestats.TbApiUsageClient; | ||
102 | import org.thingsboard.server.queue.util.AfterStartUp; | 117 | import org.thingsboard.server.queue.util.AfterStartUp; |
103 | import org.thingsboard.server.queue.util.TbTransportComponent; | 118 | import org.thingsboard.server.queue.util.TbTransportComponent; |
104 | 119 | ||
105 | -import javax.annotation.PostConstruct; | ||
106 | -import javax.annotation.PreDestroy; | ||
107 | -import java.util.Collections; | ||
108 | -import java.util.HashSet; | ||
109 | -import java.util.LinkedHashMap; | ||
110 | -import java.util.List; | ||
111 | -import java.util.Map; | ||
112 | -import java.util.Optional; | ||
113 | -import java.util.Random; | ||
114 | -import java.util.Set; | ||
115 | -import java.util.UUID; | ||
116 | -import java.util.concurrent.*; | ||
117 | -import java.util.concurrent.atomic.AtomicInteger; | ||
118 | -import java.util.stream.Collectors; | ||
119 | - | ||
120 | -import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.EVENT_IDENTIFIER; | ||
121 | - | ||
122 | -/** | ||
123 | - * Created by ashvayka on 17.10.18. | ||
124 | - */ | 120 | +/** Created by ashvayka on 17.10.18. */ |
125 | @Slf4j | 121 | @Slf4j |
126 | @Service | 122 | @Service |
123 | +@Order(value = 3) | ||
127 | @TbTransportComponent | 124 | @TbTransportComponent |
128 | public class DefaultTransportService implements TransportService { | 125 | public class DefaultTransportService implements TransportService { |
129 | 126 | ||
130 | - public static final String OVERWRITE_ACTIVITY_TIME = "overwriteActivityTime"; | ||
131 | - public static final String SESSION_EXPIRED_MESSAGE = "Session has expired due to last activity time!"; | ||
132 | - public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_OPEN = getSessionEventMsg(TransportProtos.SessionEvent.OPEN); | ||
133 | - public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_CLOSED = getSessionEventMsg(TransportProtos.SessionEvent.CLOSED); | ||
134 | - public static final TransportProtos.SessionCloseNotificationProto SESSION_CLOSE_NOTIFICATION_PROTO = TransportProtos.SessionCloseNotificationProto.newBuilder() | ||
135 | - .setMessage(SESSION_EXPIRED_MESSAGE).build(); | ||
136 | - public static final TransportProtos.SubscribeToAttributeUpdatesMsg SUBSCRIBE_TO_ATTRIBUTE_UPDATES_ASYNC_MSG = TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder() | ||
137 | - .setSessionType(TransportProtos.SessionType.ASYNC).build(); | ||
138 | - public static final TransportProtos.SubscribeToRPCMsg SUBSCRIBE_TO_RPC_ASYNC_MSG = TransportProtos.SubscribeToRPCMsg.newBuilder() | ||
139 | - .setSessionType(TransportProtos.SessionType.ASYNC).build(); | ||
140 | - | ||
141 | - private final AtomicInteger atomicTs = new AtomicInteger(0); | ||
142 | - | ||
143 | - @Value("${transport.log.enabled:true}") | ||
144 | - private boolean logEnabled; | ||
145 | - @Value("${transport.log.max_length:1024}") | ||
146 | - private int logMaxLength; | ||
147 | - @Value("${transport.sessions.inactivity_timeout}") | ||
148 | - private long sessionInactivityTimeout; | ||
149 | - @Value("${transport.sessions.report_timeout}") | ||
150 | - private long sessionReportTimeout; | ||
151 | - @Value("${transport.client_side_rpc.timeout:60000}") | ||
152 | - private long clientSideRpcTimeout; | ||
153 | - @Value("${queue.transport.poll_interval}") | ||
154 | - private int notificationsPollDuration; | ||
155 | - @Value("${transport.stats.enabled:false}") | ||
156 | - private boolean statsEnabled; | ||
157 | - | ||
158 | - private final Map<String, Number> statsMap = new LinkedHashMap<>(); | ||
159 | - | ||
160 | - private final Gson gson = new Gson(); | ||
161 | - private final TbTransportQueueFactory queueProvider; | ||
162 | - private final TbQueueProducerProvider producerProvider; | ||
163 | - private final PartitionService partitionService; | ||
164 | - private final TbServiceInfoProvider serviceInfoProvider; | ||
165 | - private final StatsFactory statsFactory; | ||
166 | - private final TransportDeviceProfileCache deviceProfileCache; | ||
167 | - private final TransportTenantProfileCache tenantProfileCache; | ||
168 | - private final TbApiUsageClient apiUsageClient; | ||
169 | - private final TransportRateLimitService rateLimitService; | ||
170 | - private final DataDecodingEncodingService dataDecodingEncodingService; | ||
171 | - private final SchedulerComponent scheduler; | ||
172 | - private final ApplicationEventPublisher eventPublisher; | ||
173 | - private final TransportResourceCache transportResourceCache; | ||
174 | - | ||
175 | - | ||
176 | - protected TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> transportApiRequestTemplate; | ||
177 | - protected TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> ruleEngineMsgProducer; | ||
178 | - protected TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> tbCoreMsgProducer; | ||
179 | - protected TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> transportNotificationsConsumer; | ||
180 | - | ||
181 | - protected MessagesStats ruleEngineProducerStats; | ||
182 | - protected MessagesStats tbCoreProducerStats; | ||
183 | - protected MessagesStats transportApiStats; | ||
184 | - | ||
185 | - protected ExecutorService transportCallbackExecutor; | ||
186 | - private ExecutorService mainConsumerExecutor; | ||
187 | - | ||
188 | - private final ConcurrentMap<UUID, SessionMetaData> sessions = new ConcurrentHashMap<>(); | ||
189 | - private final ConcurrentMap<UUID, SessionActivityData> sessionsActivity = new ConcurrentHashMap<>(); | ||
190 | - private final Map<String, RpcRequestMetadata> toServerRpcPendingMap = new ConcurrentHashMap<>(); | ||
191 | - | ||
192 | - @Getter | ||
193 | - /**TCP协议的鉴权脚本*/ | ||
194 | - private final ConcurrentSkipListSet<UUID> authScripts = new ConcurrentSkipListSet<>(); | ||
195 | - private volatile boolean stopped = false; | ||
196 | - | ||
197 | - public DefaultTransportService(TbServiceInfoProvider serviceInfoProvider, | ||
198 | - TbTransportQueueFactory queueProvider, | ||
199 | - TbQueueProducerProvider producerProvider, | ||
200 | - PartitionService partitionService, | ||
201 | - StatsFactory statsFactory, | ||
202 | - TransportDeviceProfileCache deviceProfileCache, | ||
203 | - TransportTenantProfileCache tenantProfileCache, | ||
204 | - TbApiUsageClient apiUsageClient, TransportRateLimitService rateLimitService, | ||
205 | - DataDecodingEncodingService dataDecodingEncodingService, SchedulerComponent scheduler, TransportResourceCache transportResourceCache, | ||
206 | - ApplicationEventPublisher eventPublisher) { | ||
207 | - this.serviceInfoProvider = serviceInfoProvider; | ||
208 | - this.queueProvider = queueProvider; | ||
209 | - this.producerProvider = producerProvider; | ||
210 | - this.partitionService = partitionService; | ||
211 | - this.statsFactory = statsFactory; | ||
212 | - this.deviceProfileCache = deviceProfileCache; | ||
213 | - this.tenantProfileCache = tenantProfileCache; | ||
214 | - this.apiUsageClient = apiUsageClient; | ||
215 | - this.rateLimitService = rateLimitService; | ||
216 | - this.dataDecodingEncodingService = dataDecodingEncodingService; | ||
217 | - this.scheduler = scheduler; | ||
218 | - this.transportResourceCache = transportResourceCache; | ||
219 | - this.eventPublisher = eventPublisher; | ||
220 | - } | ||
221 | - | ||
222 | - @PostConstruct | ||
223 | - public void init() { | ||
224 | - this.ruleEngineProducerStats = statsFactory.createMessagesStats(StatsType.RULE_ENGINE.getName() + ".producer"); | ||
225 | - this.tbCoreProducerStats = statsFactory.createMessagesStats(StatsType.CORE.getName() + ".producer"); | ||
226 | - this.transportApiStats = statsFactory.createMessagesStats(StatsType.TRANSPORT.getName() + ".producer"); | ||
227 | - this.transportCallbackExecutor = ThingsBoardExecutors.newWorkStealingPool(20, getClass()); | ||
228 | - this.scheduler.scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) sessionReportTimeout), sessionReportTimeout, TimeUnit.MILLISECONDS); | ||
229 | - this.scheduler.scheduleAtFixedRate(this::invalidateRateLimits, new Random().nextInt((int) sessionReportTimeout), sessionReportTimeout, TimeUnit.MILLISECONDS); | ||
230 | - transportApiRequestTemplate = queueProvider.createTransportApiRequestTemplate(); | ||
231 | - transportApiRequestTemplate.setMessagesStats(transportApiStats); | ||
232 | - ruleEngineMsgProducer = producerProvider.getRuleEngineMsgProducer(); | ||
233 | - tbCoreMsgProducer = producerProvider.getTbCoreMsgProducer(); | ||
234 | - transportNotificationsConsumer = queueProvider.createTransportNotificationsConsumer(); | ||
235 | - TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_TRANSPORT, serviceInfoProvider.getServiceId()); | ||
236 | - transportNotificationsConsumer.subscribe(Collections.singleton(tpi)); | ||
237 | - transportApiRequestTemplate.init(); | ||
238 | - mainConsumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("transport-consumer")); | ||
239 | - } | ||
240 | - | ||
241 | - @AfterStartUp | ||
242 | - private void start() { | ||
243 | - mainConsumerExecutor.execute(() -> { | ||
244 | - while (!stopped) { | ||
245 | - try { | ||
246 | - List<TbProtoQueueMsg<ToTransportMsg>> records = transportNotificationsConsumer.poll(notificationsPollDuration); | ||
247 | - if (records.size() == 0) { | ||
248 | - continue; | ||
249 | - } | ||
250 | - records.forEach(record -> { | ||
251 | - try { | ||
252 | - processToTransportMsg(record.getValue()); | ||
253 | - } catch (Throwable e) { | ||
254 | - log.warn("Failed to process the notification.", e); | ||
255 | - } | ||
256 | - }); | ||
257 | - transportNotificationsConsumer.commit(); | ||
258 | - } catch (Exception e) { | ||
259 | - if (!stopped) { | ||
260 | - log.warn("Failed to obtain messages from queue.", e); | ||
261 | - try { | ||
262 | - Thread.sleep(notificationsPollDuration); | ||
263 | - } catch (InterruptedException e2) { | ||
264 | - log.trace("Failed to wait until the server has capacity to handle new requests", e2); | ||
265 | - } | 127 | + public static final String OVERWRITE_ACTIVITY_TIME = "overwriteActivityTime"; |
128 | + public static final String SESSION_EXPIRED_MESSAGE = | ||
129 | + "Session has expired due to last activity time!"; | ||
130 | + public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_OPEN = | ||
131 | + getSessionEventMsg(TransportProtos.SessionEvent.OPEN); | ||
132 | + public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_CLOSED = | ||
133 | + getSessionEventMsg(TransportProtos.SessionEvent.CLOSED); | ||
134 | + public static final TransportProtos.SessionCloseNotificationProto | ||
135 | + SESSION_CLOSE_NOTIFICATION_PROTO = | ||
136 | + TransportProtos.SessionCloseNotificationProto.newBuilder() | ||
137 | + .setMessage(SESSION_EXPIRED_MESSAGE) | ||
138 | + .build(); | ||
139 | + public static final TransportProtos.SubscribeToAttributeUpdatesMsg | ||
140 | + SUBSCRIBE_TO_ATTRIBUTE_UPDATES_ASYNC_MSG = | ||
141 | + TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder() | ||
142 | + .setSessionType(TransportProtos.SessionType.ASYNC) | ||
143 | + .build(); | ||
144 | + public static final TransportProtos.SubscribeToRPCMsg SUBSCRIBE_TO_RPC_ASYNC_MSG = | ||
145 | + TransportProtos.SubscribeToRPCMsg.newBuilder() | ||
146 | + .setSessionType(TransportProtos.SessionType.ASYNC) | ||
147 | + .build(); | ||
148 | + | ||
149 | + private final AtomicInteger atomicTs = new AtomicInteger(0); | ||
150 | + | ||
151 | + @Value("${transport.log.enabled:true}") | ||
152 | + private boolean logEnabled; | ||
153 | + | ||
154 | + @Value("${transport.log.max_length:1024}") | ||
155 | + private int logMaxLength; | ||
156 | + | ||
157 | + @Value("${transport.sessions.inactivity_timeout}") | ||
158 | + private long sessionInactivityTimeout; | ||
159 | + | ||
160 | + @Value("${transport.sessions.report_timeout}") | ||
161 | + private long sessionReportTimeout; | ||
162 | + | ||
163 | + @Value("${transport.client_side_rpc.timeout:60000}") | ||
164 | + private long clientSideRpcTimeout; | ||
165 | + | ||
166 | + @Value("${queue.transport.poll_interval}") | ||
167 | + private int notificationsPollDuration; | ||
168 | + | ||
169 | + @Value("${transport.stats.enabled:false}") | ||
170 | + private boolean statsEnabled; | ||
171 | + | ||
172 | + private final Map<String, Number> statsMap = new LinkedHashMap<>(); | ||
173 | + | ||
174 | + private final Gson gson = new Gson(); | ||
175 | + private final TbTransportQueueFactory queueProvider; | ||
176 | + private final TbQueueProducerProvider producerProvider; | ||
177 | + private final PartitionService partitionService; | ||
178 | + private final TbServiceInfoProvider serviceInfoProvider; | ||
179 | + private final StatsFactory statsFactory; | ||
180 | + private final TransportDeviceProfileCache deviceProfileCache; | ||
181 | + private final TransportTenantProfileCache tenantProfileCache; | ||
182 | + private final TbApiUsageClient apiUsageClient; | ||
183 | + private final TransportRateLimitService rateLimitService; | ||
184 | + private final DataDecodingEncodingService dataDecodingEncodingService; | ||
185 | + private final SchedulerComponent scheduler; | ||
186 | + private final ApplicationEventPublisher eventPublisher; | ||
187 | + private final TransportResourceCache transportResourceCache; | ||
188 | + | ||
189 | + protected TbQueueRequestTemplate< | ||
190 | + TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> | ||
191 | + transportApiRequestTemplate; | ||
192 | + protected TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> ruleEngineMsgProducer; | ||
193 | + protected TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> tbCoreMsgProducer; | ||
194 | + protected TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> transportNotificationsConsumer; | ||
195 | + | ||
196 | + protected MessagesStats ruleEngineProducerStats; | ||
197 | + protected MessagesStats tbCoreProducerStats; | ||
198 | + protected MessagesStats transportApiStats; | ||
199 | + | ||
200 | + protected ExecutorService transportCallbackExecutor; | ||
201 | + private ExecutorService mainConsumerExecutor; | ||
202 | + | ||
203 | + private final ConcurrentMap<UUID, SessionMetaData> sessions = new ConcurrentHashMap<>(); | ||
204 | + private final ConcurrentMap<UUID, SessionActivityData> sessionsActivity = | ||
205 | + new ConcurrentHashMap<>(); | ||
206 | + private final Map<String, RpcRequestMetadata> toServerRpcPendingMap = new ConcurrentHashMap<>(); | ||
207 | + | ||
208 | + @Getter | ||
209 | + /** TCP协议的鉴权脚本 */ | ||
210 | + private final ConcurrentSkipListSet<UUID> authScripts = new ConcurrentSkipListSet<>(); | ||
211 | + | ||
212 | + private volatile boolean stopped = false; | ||
213 | + | ||
214 | + public DefaultTransportService( | ||
215 | + TbServiceInfoProvider serviceInfoProvider, | ||
216 | + TbTransportQueueFactory queueProvider, | ||
217 | + TbQueueProducerProvider producerProvider, | ||
218 | + PartitionService partitionService, | ||
219 | + StatsFactory statsFactory, | ||
220 | + TransportDeviceProfileCache deviceProfileCache, | ||
221 | + TransportTenantProfileCache tenantProfileCache, | ||
222 | + TbApiUsageClient apiUsageClient, | ||
223 | + TransportRateLimitService rateLimitService, | ||
224 | + DataDecodingEncodingService dataDecodingEncodingService, | ||
225 | + SchedulerComponent scheduler, | ||
226 | + TransportResourceCache transportResourceCache, | ||
227 | + ApplicationEventPublisher eventPublisher) { | ||
228 | + this.serviceInfoProvider = serviceInfoProvider; | ||
229 | + this.queueProvider = queueProvider; | ||
230 | + this.producerProvider = producerProvider; | ||
231 | + this.partitionService = partitionService; | ||
232 | + this.statsFactory = statsFactory; | ||
233 | + this.deviceProfileCache = deviceProfileCache; | ||
234 | + this.tenantProfileCache = tenantProfileCache; | ||
235 | + this.apiUsageClient = apiUsageClient; | ||
236 | + this.rateLimitService = rateLimitService; | ||
237 | + this.dataDecodingEncodingService = dataDecodingEncodingService; | ||
238 | + this.scheduler = scheduler; | ||
239 | + this.transportResourceCache = transportResourceCache; | ||
240 | + this.eventPublisher = eventPublisher; | ||
241 | + } | ||
242 | + | ||
243 | + @PostConstruct | ||
244 | + public void init() { | ||
245 | + this.ruleEngineProducerStats = | ||
246 | + statsFactory.createMessagesStats(StatsType.RULE_ENGINE.getName() + ".producer"); | ||
247 | + this.tbCoreProducerStats = | ||
248 | + statsFactory.createMessagesStats(StatsType.CORE.getName() + ".producer"); | ||
249 | + this.transportApiStats = | ||
250 | + statsFactory.createMessagesStats(StatsType.TRANSPORT.getName() + ".producer"); | ||
251 | + this.transportCallbackExecutor = ThingsBoardExecutors.newWorkStealingPool(20, getClass()); | ||
252 | + this.scheduler.scheduleAtFixedRate( | ||
253 | + this::checkInactivityAndReportActivity, | ||
254 | + new Random().nextInt((int) sessionReportTimeout), | ||
255 | + sessionReportTimeout, | ||
256 | + TimeUnit.MILLISECONDS); | ||
257 | + this.scheduler.scheduleAtFixedRate( | ||
258 | + this::invalidateRateLimits, | ||
259 | + new Random().nextInt((int) sessionReportTimeout), | ||
260 | + sessionReportTimeout, | ||
261 | + TimeUnit.MILLISECONDS); | ||
262 | + transportApiRequestTemplate = queueProvider.createTransportApiRequestTemplate(); | ||
263 | + transportApiRequestTemplate.setMessagesStats(transportApiStats); | ||
264 | + ruleEngineMsgProducer = producerProvider.getRuleEngineMsgProducer(); | ||
265 | + tbCoreMsgProducer = producerProvider.getTbCoreMsgProducer(); | ||
266 | + transportNotificationsConsumer = queueProvider.createTransportNotificationsConsumer(); | ||
267 | + TopicPartitionInfo tpi = | ||
268 | + partitionService.getNotificationsTopic( | ||
269 | + ServiceType.TB_TRANSPORT, serviceInfoProvider.getServiceId()); | ||
270 | + transportNotificationsConsumer.subscribe(Collections.singleton(tpi)); | ||
271 | + transportApiRequestTemplate.init(); | ||
272 | + mainConsumerExecutor = | ||
273 | + Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("transport-consumer")); | ||
274 | + } | ||
275 | + | ||
276 | + @AfterStartUp | ||
277 | + private void start() { | ||
278 | + mainConsumerExecutor.execute( | ||
279 | + () -> { | ||
280 | + while (!stopped) { | ||
281 | + try { | ||
282 | + List<TbProtoQueueMsg<ToTransportMsg>> records = | ||
283 | + transportNotificationsConsumer.poll(notificationsPollDuration); | ||
284 | + if (records.size() == 0) { | ||
285 | + continue; | ||
286 | + } | ||
287 | + records.forEach( | ||
288 | + record -> { | ||
289 | + try { | ||
290 | + processToTransportMsg(record.getValue()); | ||
291 | + } catch (Throwable e) { | ||
292 | + log.warn("Failed to process the notification.", e); | ||
266 | } | 293 | } |
294 | + }); | ||
295 | + transportNotificationsConsumer.commit(); | ||
296 | + } catch (Exception e) { | ||
297 | + if (!stopped) { | ||
298 | + log.warn("Failed to obtain messages from queue.", e); | ||
299 | + try { | ||
300 | + Thread.sleep(notificationsPollDuration); | ||
301 | + } catch (InterruptedException e2) { | ||
302 | + log.trace( | ||
303 | + "Failed to wait until the server has capacity to handle new requests", e2); | ||
267 | } | 304 | } |
305 | + } | ||
268 | } | 306 | } |
307 | + } | ||
269 | }); | 308 | }); |
270 | - } | ||
271 | - | ||
272 | - private void invalidateRateLimits() { | ||
273 | - rateLimitService.invalidateRateLimitsIpTable(sessionInactivityTimeout); | ||
274 | - } | ||
275 | - | ||
276 | - @PreDestroy | ||
277 | - public void destroy() { | ||
278 | - stopped = true; | ||
279 | - | ||
280 | - if (transportNotificationsConsumer != null) { | ||
281 | - transportNotificationsConsumer.unsubscribe(); | ||
282 | - } | ||
283 | - if (transportCallbackExecutor != null) { | ||
284 | - transportCallbackExecutor.shutdownNow(); | ||
285 | - } | ||
286 | - if (mainConsumerExecutor != null) { | ||
287 | - mainConsumerExecutor.shutdownNow(); | ||
288 | - } | ||
289 | - if (transportApiRequestTemplate != null) { | ||
290 | - transportApiRequestTemplate.stop(); | ||
291 | - } | ||
292 | - } | ||
293 | - | ||
294 | - @Override | ||
295 | - public SessionMetaData registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) { | ||
296 | - return sessions.computeIfAbsent(toSessionId(sessionInfo), (x) -> new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener)); | ||
297 | - } | ||
298 | - | ||
299 | - @Override | ||
300 | - public TransportProtos.GetEntityProfileResponseMsg getEntityProfile(TransportProtos.GetEntityProfileRequestMsg msg) { | ||
301 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
302 | - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setEntityProfileRequestMsg(msg).build()); | ||
303 | - try { | ||
304 | - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
305 | - return response.getValue().getEntityProfileResponseMsg(); | ||
306 | - } catch (InterruptedException | ExecutionException e) { | ||
307 | - throw new RuntimeException(e); | ||
308 | - } | ||
309 | - } | ||
310 | - | ||
311 | - @Override | ||
312 | - public TransportProtos.GetResourceResponseMsg getResource(TransportProtos.GetResourceRequestMsg msg) { | ||
313 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
314 | - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setResourceRequestMsg(msg).build()); | ||
315 | - try { | ||
316 | - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
317 | - return response.getValue().getResourceResponseMsg(); | ||
318 | - } catch (InterruptedException | ExecutionException e) { | ||
319 | - throw new RuntimeException(e); | ||
320 | - } | ||
321 | - } | ||
322 | - | ||
323 | - | ||
324 | - | ||
325 | - @Override | ||
326 | - public TransportProtos.GetSnmpDevicesResponseMsg getSnmpDevicesIds(TransportProtos.GetSnmpDevicesRequestMsg requestMsg) { | ||
327 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>( | ||
328 | - UUID.randomUUID(), TransportApiRequestMsg.newBuilder() | ||
329 | - .setSnmpDevicesRequestMsg(requestMsg) | ||
330 | - .build() | ||
331 | - ); | ||
332 | - | ||
333 | - try { | ||
334 | - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
335 | - return response.getValue().getSnmpDevicesResponseMsg(); | ||
336 | - } catch (InterruptedException | ExecutionException e) { | ||
337 | - throw new RuntimeException(e); | ||
338 | - } | ||
339 | - } | ||
340 | - | ||
341 | - @Override | ||
342 | - public TransportProtos.GetDeviceResponseMsg getDevice(TransportProtos.GetDeviceRequestMsg requestMsg) { | ||
343 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>( | ||
344 | - UUID.randomUUID(), TransportApiRequestMsg.newBuilder() | ||
345 | - .setDeviceRequestMsg(requestMsg) | ||
346 | - .build() | ||
347 | - ); | ||
348 | - | ||
349 | - try { | ||
350 | - TransportApiResponseMsg response = transportApiRequestTemplate.send(protoMsg).get().getValue(); | ||
351 | - if (response.hasDeviceResponseMsg()) { | ||
352 | - return response.getDeviceResponseMsg(); | ||
353 | - } else { | ||
354 | - return null; | ||
355 | - } | ||
356 | - } catch (InterruptedException | ExecutionException e) { | ||
357 | - throw new RuntimeException(e); | ||
358 | - } | ||
359 | - } | ||
360 | - | ||
361 | - @Override | ||
362 | - public TransportProtos.GetDeviceCredentialsResponseMsg getDeviceCredentials(TransportProtos.GetDeviceCredentialsRequestMsg requestMsg) { | ||
363 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>( | ||
364 | - UUID.randomUUID(), TransportApiRequestMsg.newBuilder() | ||
365 | - .setDeviceCredentialsRequestMsg(requestMsg) | ||
366 | - .build() | ||
367 | - ); | ||
368 | - | ||
369 | - try { | ||
370 | - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
371 | - return response.getValue().getDeviceCredentialsResponseMsg(); | ||
372 | - } catch (InterruptedException | ExecutionException e) { | ||
373 | - throw new RuntimeException(e); | ||
374 | - } | ||
375 | - } | ||
376 | - | ||
377 | - @Override | ||
378 | - public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg, | ||
379 | - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
380 | - log.trace("Processing msg: {}", msg); | ||
381 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), | ||
382 | - TransportApiRequestMsg.newBuilder().setValidateTokenRequestMsg(msg).build()); | ||
383 | - doProcess(transportType, protoMsg, callback); | ||
384 | - } | ||
385 | - | ||
386 | - @Override | ||
387 | - public void process(DeviceTransportType transportType, TransportProtos.ValidateBasicMqttCredRequestMsg msg, | ||
388 | - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
389 | - log.trace("Processing msg: {}", msg); | ||
390 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), | ||
391 | - TransportApiRequestMsg.newBuilder().setValidateBasicMqttCredRequestMsg(msg).build()); | ||
392 | - doProcess(transportType, protoMsg, callback); | ||
393 | - } | ||
394 | - | ||
395 | - @Override | ||
396 | - public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg requestMsg, TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
397 | - log.trace("Processing msg: {}", requestMsg); | ||
398 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateDeviceLwM2MCredentialsRequestMsg(requestMsg).build()); | ||
399 | - ListenableFuture<ValidateDeviceCredentialsResponse> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> { | ||
400 | - TransportProtos.ValidateDeviceCredentialsResponseMsg msg = tmp.getValue().getValidateCredResponseMsg(); | ||
401 | - ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result = ValidateDeviceCredentialsResponse.builder(); | ||
402 | - if (msg.hasDeviceInfo()) { | 309 | + } |
310 | + | ||
311 | + private void invalidateRateLimits() { | ||
312 | + rateLimitService.invalidateRateLimitsIpTable(sessionInactivityTimeout); | ||
313 | + } | ||
314 | + | ||
315 | + @PreDestroy | ||
316 | + public void destroy() { | ||
317 | + stopped = true; | ||
318 | + | ||
319 | + if (transportNotificationsConsumer != null) { | ||
320 | + transportNotificationsConsumer.unsubscribe(); | ||
321 | + } | ||
322 | + if (transportCallbackExecutor != null) { | ||
323 | + transportCallbackExecutor.shutdownNow(); | ||
324 | + } | ||
325 | + if (mainConsumerExecutor != null) { | ||
326 | + mainConsumerExecutor.shutdownNow(); | ||
327 | + } | ||
328 | + if (transportApiRequestTemplate != null) { | ||
329 | + transportApiRequestTemplate.stop(); | ||
330 | + } | ||
331 | + } | ||
332 | + | ||
333 | + @Override | ||
334 | + public SessionMetaData registerAsyncSession( | ||
335 | + TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) { | ||
336 | + return sessions.computeIfAbsent( | ||
337 | + toSessionId(sessionInfo), | ||
338 | + (x) -> new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener)); | ||
339 | + } | ||
340 | + | ||
341 | + @Override | ||
342 | + public TransportProtos.GetEntityProfileResponseMsg getEntityProfile( | ||
343 | + TransportProtos.GetEntityProfileRequestMsg msg) { | ||
344 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
345 | + new TbProtoQueueMsg<>( | ||
346 | + UUID.randomUUID(), | ||
347 | + TransportApiRequestMsg.newBuilder().setEntityProfileRequestMsg(msg).build()); | ||
348 | + try { | ||
349 | + TbProtoQueueMsg<TransportApiResponseMsg> response = | ||
350 | + transportApiRequestTemplate.send(protoMsg).get(); | ||
351 | + return response.getValue().getEntityProfileResponseMsg(); | ||
352 | + } catch (InterruptedException | ExecutionException e) { | ||
353 | + throw new RuntimeException(e); | ||
354 | + } | ||
355 | + } | ||
356 | + | ||
357 | + @Override | ||
358 | + public TransportProtos.GetResourceResponseMsg getResource( | ||
359 | + TransportProtos.GetResourceRequestMsg msg) { | ||
360 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
361 | + new TbProtoQueueMsg<>( | ||
362 | + UUID.randomUUID(), | ||
363 | + TransportApiRequestMsg.newBuilder().setResourceRequestMsg(msg).build()); | ||
364 | + try { | ||
365 | + TbProtoQueueMsg<TransportApiResponseMsg> response = | ||
366 | + transportApiRequestTemplate.send(protoMsg).get(); | ||
367 | + return response.getValue().getResourceResponseMsg(); | ||
368 | + } catch (InterruptedException | ExecutionException e) { | ||
369 | + throw new RuntimeException(e); | ||
370 | + } | ||
371 | + } | ||
372 | + | ||
373 | + @Override | ||
374 | + public TransportProtos.GetSnmpDevicesResponseMsg getSnmpDevicesIds( | ||
375 | + TransportProtos.GetSnmpDevicesRequestMsg requestMsg) { | ||
376 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
377 | + new TbProtoQueueMsg<>( | ||
378 | + UUID.randomUUID(), | ||
379 | + TransportApiRequestMsg.newBuilder().setSnmpDevicesRequestMsg(requestMsg).build()); | ||
380 | + | ||
381 | + try { | ||
382 | + TbProtoQueueMsg<TransportApiResponseMsg> response = | ||
383 | + transportApiRequestTemplate.send(protoMsg).get(); | ||
384 | + return response.getValue().getSnmpDevicesResponseMsg(); | ||
385 | + } catch (InterruptedException | ExecutionException e) { | ||
386 | + throw new RuntimeException(e); | ||
387 | + } | ||
388 | + } | ||
389 | + | ||
390 | + @Override | ||
391 | + public TransportProtos.GetDeviceResponseMsg getDevice( | ||
392 | + TransportProtos.GetDeviceRequestMsg requestMsg) { | ||
393 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
394 | + new TbProtoQueueMsg<>( | ||
395 | + UUID.randomUUID(), | ||
396 | + TransportApiRequestMsg.newBuilder().setDeviceRequestMsg(requestMsg).build()); | ||
397 | + | ||
398 | + try { | ||
399 | + TransportApiResponseMsg response = | ||
400 | + transportApiRequestTemplate.send(protoMsg).get().getValue(); | ||
401 | + if (response.hasDeviceResponseMsg()) { | ||
402 | + return response.getDeviceResponseMsg(); | ||
403 | + } else { | ||
404 | + return null; | ||
405 | + } | ||
406 | + } catch (InterruptedException | ExecutionException e) { | ||
407 | + throw new RuntimeException(e); | ||
408 | + } | ||
409 | + } | ||
410 | + | ||
411 | + @Override | ||
412 | + public TransportProtos.GetDeviceCredentialsResponseMsg getDeviceCredentials( | ||
413 | + TransportProtos.GetDeviceCredentialsRequestMsg requestMsg) { | ||
414 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
415 | + new TbProtoQueueMsg<>( | ||
416 | + UUID.randomUUID(), | ||
417 | + TransportApiRequestMsg.newBuilder().setDeviceCredentialsRequestMsg(requestMsg).build()); | ||
418 | + | ||
419 | + try { | ||
420 | + TbProtoQueueMsg<TransportApiResponseMsg> response = | ||
421 | + transportApiRequestTemplate.send(protoMsg).get(); | ||
422 | + return response.getValue().getDeviceCredentialsResponseMsg(); | ||
423 | + } catch (InterruptedException | ExecutionException e) { | ||
424 | + throw new RuntimeException(e); | ||
425 | + } | ||
426 | + } | ||
427 | + | ||
428 | + @Override | ||
429 | + public void process( | ||
430 | + DeviceTransportType transportType, | ||
431 | + TransportProtos.ValidateDeviceTokenRequestMsg msg, | ||
432 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
433 | + log.trace("Processing msg: {}", msg); | ||
434 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
435 | + new TbProtoQueueMsg<>( | ||
436 | + UUID.randomUUID(), | ||
437 | + TransportApiRequestMsg.newBuilder().setValidateTokenRequestMsg(msg).build()); | ||
438 | + doProcess(transportType, protoMsg, callback); | ||
439 | + } | ||
440 | + | ||
441 | + @Override | ||
442 | + public void process( | ||
443 | + DeviceTransportType transportType, | ||
444 | + TransportProtos.ValidateBasicMqttCredRequestMsg msg, | ||
445 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
446 | + log.trace("Processing msg: {}", msg); | ||
447 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
448 | + new TbProtoQueueMsg<>( | ||
449 | + UUID.randomUUID(), | ||
450 | + TransportApiRequestMsg.newBuilder().setValidateBasicMqttCredRequestMsg(msg).build()); | ||
451 | + doProcess(transportType, protoMsg, callback); | ||
452 | + } | ||
453 | + | ||
454 | + @Override | ||
455 | + public void process( | ||
456 | + TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg requestMsg, | ||
457 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
458 | + log.trace("Processing msg: {}", requestMsg); | ||
459 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
460 | + new TbProtoQueueMsg<>( | ||
461 | + UUID.randomUUID(), | ||
462 | + TransportApiRequestMsg.newBuilder() | ||
463 | + .setValidateDeviceLwM2MCredentialsRequestMsg(requestMsg) | ||
464 | + .build()); | ||
465 | + ListenableFuture<ValidateDeviceCredentialsResponse> response = | ||
466 | + Futures.transform( | ||
467 | + transportApiRequestTemplate.send(protoMsg), | ||
468 | + tmp -> { | ||
469 | + TransportProtos.ValidateDeviceCredentialsResponseMsg msg = | ||
470 | + tmp.getValue().getValidateCredResponseMsg(); | ||
471 | + ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result = | ||
472 | + ValidateDeviceCredentialsResponse.builder(); | ||
473 | + if (msg.hasDeviceInfo()) { | ||
403 | result.credentials(msg.getCredentialsBody()); | 474 | result.credentials(msg.getCredentialsBody()); |
404 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); | 475 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); |
405 | result.deviceInfo(tdi); | 476 | result.deviceInfo(tdi); |
406 | ByteString profileBody = msg.getProfileBody(); | 477 | ByteString profileBody = msg.getProfileBody(); |
407 | if (!profileBody.isEmpty()) { | 478 | if (!profileBody.isEmpty()) { |
408 | - DeviceProfile profile = deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody); | ||
409 | - result.deviceProfile(profile); | 479 | + DeviceProfile profile = |
480 | + deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody); | ||
481 | + result.deviceProfile(profile); | ||
410 | } | 482 | } |
411 | - } | ||
412 | - return result.build(); | ||
413 | - }, MoreExecutors.directExecutor()); | ||
414 | - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
415 | - } | ||
416 | - | ||
417 | - @Override | ||
418 | - public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceX509CertRequestMsg msg, TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
419 | - log.trace("Processing msg: {}", msg); | ||
420 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateX509CertRequestMsg(msg).build()); | ||
421 | - doProcess(transportType, protoMsg, callback); | ||
422 | - } | ||
423 | - | ||
424 | - private void doProcess(DeviceTransportType transportType, TbProtoQueueMsg<TransportApiRequestMsg> protoMsg, | ||
425 | - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
426 | - ListenableFuture<ValidateDeviceCredentialsResponse> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> { | ||
427 | - TransportProtos.ValidateDeviceCredentialsResponseMsg msg = tmp.getValue().getValidateCredResponseMsg(); | ||
428 | - ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result = ValidateDeviceCredentialsResponse.builder(); | ||
429 | - if (msg.hasDeviceInfo()) { | 483 | + } |
484 | + return result.build(); | ||
485 | + }, | ||
486 | + MoreExecutors.directExecutor()); | ||
487 | + AsyncCallbackTemplate.withCallback( | ||
488 | + response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
489 | + } | ||
490 | + | ||
491 | + @Override | ||
492 | + public void process( | ||
493 | + DeviceTransportType transportType, | ||
494 | + TransportProtos.ValidateDeviceX509CertRequestMsg msg, | ||
495 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
496 | + log.trace("Processing msg: {}", msg); | ||
497 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
498 | + new TbProtoQueueMsg<>( | ||
499 | + UUID.randomUUID(), | ||
500 | + TransportApiRequestMsg.newBuilder().setValidateX509CertRequestMsg(msg).build()); | ||
501 | + doProcess(transportType, protoMsg, callback); | ||
502 | + } | ||
503 | + | ||
504 | + private void doProcess( | ||
505 | + DeviceTransportType transportType, | ||
506 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg, | ||
507 | + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) { | ||
508 | + | ||
509 | + ListenableFuture<ValidateDeviceCredentialsResponse> response = | ||
510 | + Futures.transform( | ||
511 | + transportApiRequestTemplate.send(protoMsg), | ||
512 | + tmp -> { | ||
513 | + TransportProtos.ValidateDeviceCredentialsResponseMsg msg = | ||
514 | + tmp.getValue().getValidateCredResponseMsg(); | ||
515 | + ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result = | ||
516 | + ValidateDeviceCredentialsResponse.builder(); | ||
517 | + if (msg.hasDeviceInfo()) { | ||
430 | result.credentials(msg.getCredentialsBody()); | 518 | result.credentials(msg.getCredentialsBody()); |
431 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); | 519 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); |
432 | result.deviceInfo(tdi); | 520 | result.deviceInfo(tdi); |
433 | ByteString profileBody = msg.getProfileBody(); | 521 | ByteString profileBody = msg.getProfileBody(); |
434 | if (!profileBody.isEmpty()) { | 522 | if (!profileBody.isEmpty()) { |
435 | - DeviceProfile profile = deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody); | ||
436 | - if (transportType != DeviceTransportType.DEFAULT | ||
437 | - && profile != null && profile.getTransportType() != DeviceTransportType.DEFAULT && profile.getTransportType() != transportType) { | ||
438 | - log.debug("[{}] Device profile [{}] has different transport type: {}, expected: {}", tdi.getDeviceId(), tdi.getDeviceProfileId(), profile.getTransportType(), transportType); | ||
439 | - throw new IllegalStateException("Device profile has different transport type: " + profile.getTransportType() + ". Expected: " + transportType); | ||
440 | - } | ||
441 | - result.deviceProfile(profile); | 523 | + DeviceProfile profile = |
524 | + deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody); | ||
525 | + if (transportType != DeviceTransportType.DEFAULT | ||
526 | + && profile != null | ||
527 | + && profile.getTransportType() != DeviceTransportType.DEFAULT | ||
528 | + && profile.getTransportType() != transportType) { | ||
529 | + log.debug( | ||
530 | + "[{}] Device profile [{}] has different transport type: {}, expected: {}", | ||
531 | + tdi.getDeviceId(), | ||
532 | + tdi.getDeviceProfileId(), | ||
533 | + profile.getTransportType(), | ||
534 | + transportType); | ||
535 | + throw new IllegalStateException( | ||
536 | + "Device profile has different transport type: " | ||
537 | + + profile.getTransportType() | ||
538 | + + ". Expected: " | ||
539 | + + transportType); | ||
540 | + } | ||
541 | + result.deviceProfile(profile); | ||
442 | } | 542 | } |
443 | - } | ||
444 | - return result.build(); | ||
445 | - }, MoreExecutors.directExecutor()); | ||
446 | - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
447 | - } | ||
448 | - | ||
449 | - @Override | ||
450 | - public void process(TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg requestMsg, TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback) { | ||
451 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setGetOrCreateDeviceRequestMsg(requestMsg).build()); | ||
452 | - log.trace("Processing msg: {}", requestMsg); | ||
453 | - ListenableFuture<GetOrCreateDeviceFromGatewayResponse> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> { | ||
454 | - TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg msg = tmp.getValue().getGetOrCreateDeviceResponseMsg(); | ||
455 | - GetOrCreateDeviceFromGatewayResponse.GetOrCreateDeviceFromGatewayResponseBuilder result = GetOrCreateDeviceFromGatewayResponse.builder(); | ||
456 | - if (msg.hasDeviceInfo()) { | 543 | + } |
544 | + return result.build(); | ||
545 | + }, | ||
546 | + MoreExecutors.directExecutor()); | ||
547 | + AsyncCallbackTemplate.withCallback( | ||
548 | + response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
549 | + } | ||
550 | + | ||
551 | + @Override | ||
552 | + public void process( | ||
553 | + TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg requestMsg, | ||
554 | + TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback) { | ||
555 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
556 | + new TbProtoQueueMsg<>( | ||
557 | + UUID.randomUUID(), | ||
558 | + TransportApiRequestMsg.newBuilder().setGetOrCreateDeviceRequestMsg(requestMsg).build()); | ||
559 | + log.trace("Processing msg: {}", requestMsg); | ||
560 | + ListenableFuture<GetOrCreateDeviceFromGatewayResponse> response = | ||
561 | + Futures.transform( | ||
562 | + transportApiRequestTemplate.send(protoMsg), | ||
563 | + tmp -> { | ||
564 | + TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg msg = | ||
565 | + tmp.getValue().getGetOrCreateDeviceResponseMsg(); | ||
566 | + GetOrCreateDeviceFromGatewayResponse.GetOrCreateDeviceFromGatewayResponseBuilder | ||
567 | + result = GetOrCreateDeviceFromGatewayResponse.builder(); | ||
568 | + if (msg.hasDeviceInfo()) { | ||
457 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); | 569 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); |
458 | result.deviceInfo(tdi); | 570 | result.deviceInfo(tdi); |
459 | ByteString profileBody = msg.getProfileBody(); | 571 | ByteString profileBody = msg.getProfileBody(); |
460 | if (profileBody != null && !profileBody.isEmpty()) { | 572 | if (profileBody != null && !profileBody.isEmpty()) { |
461 | - result.deviceProfile(deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody)); | 573 | + result.deviceProfile( |
574 | + deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody)); | ||
462 | } | 575 | } |
463 | - } | ||
464 | - return result.build(); | ||
465 | - }, MoreExecutors.directExecutor()); | ||
466 | - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
467 | - } | ||
468 | - | ||
469 | - @Override | ||
470 | - public void process(TransportProtos.LwM2MRequestMsg msg, TransportServiceCallback<TransportProtos.LwM2MResponseMsg> callback) { | ||
471 | - log.trace("Processing msg: {}", msg); | ||
472 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), | ||
473 | - TransportApiRequestMsg.newBuilder().setLwM2MRequestMsg(msg).build()); | ||
474 | - AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), | ||
475 | - response -> callback.onSuccess(response.getValue().getLwM2MResponseMsg()), callback::onError, transportCallbackExecutor); | ||
476 | - } | ||
477 | - | ||
478 | - private TransportDeviceInfo getTransportDeviceInfo(TransportProtos.DeviceInfoProto di) { | ||
479 | - TransportDeviceInfo tdi = new TransportDeviceInfo(); | ||
480 | - tdi.setTenantId(TenantId.fromUUID(new UUID(di.getTenantIdMSB(), di.getTenantIdLSB()))); | ||
481 | - tdi.setCustomerId(new CustomerId(new UUID(di.getCustomerIdMSB(), di.getCustomerIdLSB()))); | ||
482 | - tdi.setDeviceId(new DeviceId(new UUID(di.getDeviceIdMSB(), di.getDeviceIdLSB()))); | ||
483 | - tdi.setDeviceProfileId(new DeviceProfileId(new UUID(di.getDeviceProfileIdMSB(), di.getDeviceProfileIdLSB()))); | ||
484 | - tdi.setAdditionalInfo(di.getAdditionalInfo()); | ||
485 | - tdi.setDeviceName(di.getDeviceName()); | ||
486 | - tdi.setDeviceType(di.getDeviceType()); | ||
487 | - if (StringUtils.isNotEmpty(di.getPowerMode())) { | ||
488 | - tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode())); | ||
489 | - tdi.setEdrxCycle(di.getEdrxCycle()); | ||
490 | - tdi.setPsmActivityTimer(di.getPsmActivityTimer()); | ||
491 | - tdi.setPagingTransmissionWindow(di.getPagingTransmissionWindow()); | ||
492 | - } | ||
493 | - return tdi; | ||
494 | - } | ||
495 | - | ||
496 | - @Override | ||
497 | - public void process(ProvisionDeviceRequestMsg requestMsg, TransportServiceCallback<ProvisionDeviceResponseMsg> callback) { | ||
498 | - log.trace("Processing msg: {}", requestMsg); | ||
499 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setProvisionDeviceRequestMsg(requestMsg).build()); | ||
500 | - ListenableFuture<ProvisionDeviceResponseMsg> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> | ||
501 | - tmp.getValue().getProvisionDeviceResponseMsg() | ||
502 | - , MoreExecutors.directExecutor()); | ||
503 | - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
504 | - } | ||
505 | - | ||
506 | - @Override | ||
507 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SubscriptionInfoProto msg, TransportServiceCallback<Void> callback) { | ||
508 | - if (log.isTraceEnabled()) { | ||
509 | - log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg); | 576 | + } |
577 | + return result.build(); | ||
578 | + }, | ||
579 | + MoreExecutors.directExecutor()); | ||
580 | + AsyncCallbackTemplate.withCallback( | ||
581 | + response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
582 | + } | ||
583 | + | ||
584 | + @Override | ||
585 | + public void process( | ||
586 | + TransportProtos.LwM2MRequestMsg msg, | ||
587 | + TransportServiceCallback<TransportProtos.LwM2MResponseMsg> callback) { | ||
588 | + log.trace("Processing msg: {}", msg); | ||
589 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
590 | + new TbProtoQueueMsg<>( | ||
591 | + UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setLwM2MRequestMsg(msg).build()); | ||
592 | + AsyncCallbackTemplate.withCallback( | ||
593 | + transportApiRequestTemplate.send(protoMsg), | ||
594 | + response -> callback.onSuccess(response.getValue().getLwM2MResponseMsg()), | ||
595 | + callback::onError, | ||
596 | + transportCallbackExecutor); | ||
597 | + } | ||
598 | + | ||
599 | + private TransportDeviceInfo getTransportDeviceInfo(TransportProtos.DeviceInfoProto di) { | ||
600 | + TransportDeviceInfo tdi = new TransportDeviceInfo(); | ||
601 | + tdi.setTenantId(TenantId.fromUUID(new UUID(di.getTenantIdMSB(), di.getTenantIdLSB()))); | ||
602 | + tdi.setCustomerId(new CustomerId(new UUID(di.getCustomerIdMSB(), di.getCustomerIdLSB()))); | ||
603 | + tdi.setDeviceId(new DeviceId(new UUID(di.getDeviceIdMSB(), di.getDeviceIdLSB()))); | ||
604 | + tdi.setDeviceProfileId( | ||
605 | + new DeviceProfileId(new UUID(di.getDeviceProfileIdMSB(), di.getDeviceProfileIdLSB()))); | ||
606 | + tdi.setAdditionalInfo(di.getAdditionalInfo()); | ||
607 | + tdi.setDeviceName(di.getDeviceName()); | ||
608 | + tdi.setDeviceType(di.getDeviceType()); | ||
609 | + if (StringUtils.isNotEmpty(di.getPowerMode())) { | ||
610 | + tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode())); | ||
611 | + tdi.setEdrxCycle(di.getEdrxCycle()); | ||
612 | + tdi.setPsmActivityTimer(di.getPsmActivityTimer()); | ||
613 | + tdi.setPagingTransmissionWindow(di.getPagingTransmissionWindow()); | ||
614 | + } | ||
615 | + return tdi; | ||
616 | + } | ||
617 | + | ||
618 | + @Override | ||
619 | + public void process( | ||
620 | + ProvisionDeviceRequestMsg requestMsg, | ||
621 | + TransportServiceCallback<ProvisionDeviceResponseMsg> callback) { | ||
622 | + log.trace("Processing msg: {}", requestMsg); | ||
623 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
624 | + new TbProtoQueueMsg<>( | ||
625 | + UUID.randomUUID(), | ||
626 | + TransportApiRequestMsg.newBuilder().setProvisionDeviceRequestMsg(requestMsg).build()); | ||
627 | + ListenableFuture<ProvisionDeviceResponseMsg> response = | ||
628 | + Futures.transform( | ||
629 | + transportApiRequestTemplate.send(protoMsg), | ||
630 | + tmp -> tmp.getValue().getProvisionDeviceResponseMsg(), | ||
631 | + MoreExecutors.directExecutor()); | ||
632 | + AsyncCallbackTemplate.withCallback( | ||
633 | + response, callback::onSuccess, callback::onError, transportCallbackExecutor); | ||
634 | + } | ||
635 | + | ||
636 | + @Override | ||
637 | + public void process( | ||
638 | + TransportProtos.SessionInfoProto sessionInfo, | ||
639 | + TransportProtos.SubscriptionInfoProto msg, | ||
640 | + TransportServiceCallback<Void> callback) { | ||
641 | + if (log.isTraceEnabled()) { | ||
642 | + log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg); | ||
643 | + } | ||
644 | + sendToDeviceActor( | ||
645 | + sessionInfo, | ||
646 | + TransportToDeviceActorMsg.newBuilder() | ||
647 | + .setSessionInfo(sessionInfo) | ||
648 | + .setSubscriptionInfo(msg) | ||
649 | + .build(), | ||
650 | + callback); | ||
651 | + } | ||
652 | + | ||
653 | + @Override | ||
654 | + public void process( | ||
655 | + TransportProtos.SessionInfoProto sessionInfo, | ||
656 | + TransportProtos.SessionEventMsg msg, | ||
657 | + TransportServiceCallback<Void> callback) { | ||
658 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
659 | + reportActivityInternal(sessionInfo); | ||
660 | + sendToDeviceActor( | ||
661 | + sessionInfo, | ||
662 | + TransportToDeviceActorMsg.newBuilder() | ||
663 | + .setSessionInfo(sessionInfo) | ||
664 | + .setSessionEvent(msg) | ||
665 | + .build(), | ||
666 | + callback); | ||
667 | + } | ||
668 | + } | ||
669 | + | ||
670 | + @Override | ||
671 | + public void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback) { | ||
672 | + TransportProtos.SessionInfoProto sessionInfo = msg.getSessionInfo(); | ||
673 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
674 | + SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo)); | ||
675 | + if (sessionMetaData != null) { | ||
676 | + if (msg.hasSubscribeToAttributes()) { | ||
677 | + sessionMetaData.setSubscribedToAttributes(true); | ||
510 | } | 678 | } |
511 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo) | ||
512 | - .setSubscriptionInfo(msg).build(), callback); | ||
513 | - } | ||
514 | - | ||
515 | - @Override | ||
516 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SessionEventMsg msg, TransportServiceCallback<Void> callback) { | ||
517 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
518 | - reportActivityInternal(sessionInfo); | ||
519 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo) | ||
520 | - .setSessionEvent(msg).build(), callback); | 679 | + if (msg.hasSubscribeToRPC()) { |
680 | + sessionMetaData.setSubscribedToRPC(true); | ||
521 | } | 681 | } |
522 | - } | ||
523 | - | ||
524 | - @Override | ||
525 | - public void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback) { | ||
526 | - TransportProtos.SessionInfoProto sessionInfo = msg.getSessionInfo(); | ||
527 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
528 | - SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo)); | ||
529 | - if (sessionMetaData != null) { | ||
530 | - if (msg.hasSubscribeToAttributes()) { | ||
531 | - sessionMetaData.setSubscribedToAttributes(true); | ||
532 | - } | ||
533 | - if (msg.hasSubscribeToRPC()) { | ||
534 | - sessionMetaData.setSubscribedToRPC(true); | ||
535 | - } | ||
536 | - } | ||
537 | - | ||
538 | - reportActivityInternal(sessionInfo); | ||
539 | - sendToDeviceActor(sessionInfo, msg, callback); | ||
540 | - } | ||
541 | - } | ||
542 | - | ||
543 | - @Override | ||
544 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.PostTelemetryMsg msg, TransportServiceCallback<Void> callback) { | ||
545 | - int dataPoints = 0; | ||
546 | - for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { | ||
547 | - dataPoints += tsKv.getKvCount(); | ||
548 | - } | ||
549 | - if (checkLimits(sessionInfo, msg, callback, dataPoints)) { | ||
550 | - reportActivityInternal(sessionInfo); | ||
551 | - TenantId tenantId = getTenantId(sessionInfo); | ||
552 | - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
553 | - CustomerId customerId = getCustomerId(sessionInfo); | ||
554 | - MsgPackCallback packCallback = new MsgPackCallback(msg.getTsKvListCount(), new ApiStatsProxyCallback<>(tenantId, customerId, dataPoints, callback)); | ||
555 | - for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { | ||
556 | - TbMsgMetaData metaData = new TbMsgMetaData(); | ||
557 | - metaData.putValue("deviceName", sessionInfo.getDeviceName()); | ||
558 | - metaData.putValue("deviceType", sessionInfo.getDeviceType()); | ||
559 | - metaData.putValue("ts", tsKv.getTs() + ""); | ||
560 | - JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList()); | ||
561 | - sendToRuleEngine(tenantId, deviceId, customerId, sessionInfo, json, metaData, SessionMsgType.POST_TELEMETRY_REQUEST, packCallback); | ||
562 | - } | ||
563 | - } | ||
564 | - } | ||
565 | - | ||
566 | - @Override | ||
567 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.PostAttributeMsg msg, TransportServiceCallback<Void> callback) { | ||
568 | - if (checkLimits(sessionInfo, msg, callback, msg.getKvCount())) { | ||
569 | - reportActivityInternal(sessionInfo); | ||
570 | - TenantId tenantId = getTenantId(sessionInfo); | ||
571 | - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
572 | - JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); | ||
573 | - TbMsgMetaData metaData = new TbMsgMetaData(); | ||
574 | - metaData.putValue("deviceName", sessionInfo.getDeviceName()); | ||
575 | - metaData.putValue("deviceType", sessionInfo.getDeviceType()); | ||
576 | - metaData.putValue("notifyDevice", "false"); | ||
577 | - CustomerId customerId = getCustomerId(sessionInfo); | ||
578 | - sendToRuleEngine(tenantId, deviceId, customerId, sessionInfo, json, metaData, SessionMsgType.POST_ATTRIBUTES_REQUEST, | ||
579 | - new TransportTbQueueCallback(new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback))); | ||
580 | - } | ||
581 | - } | ||
582 | - //thingskit | ||
583 | - @Override | ||
584 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.PostEventMsg msg, | ||
585 | - TransportServiceCallback<Void> callback,String topicName) { | ||
586 | - //Topic地址:v1/devices/event/${deviceIdentifier}/${identifier} | ||
587 | - //${deviceIdentifier} 标识支持deviceId/deviceName即SN | ||
588 | - String[] topicInfo = topicName.split(MqttTopics.BASE_DEVICE_EVENT_TOPIC + "/"); | ||
589 | - if(null == topicInfo || topicInfo.length !=2){ | ||
590 | - throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage()); | ||
591 | - } | ||
592 | - String[] eventInfo = topicInfo[1].split("/"); | ||
593 | - if(null == eventInfo || eventInfo.length !=2){ | ||
594 | - throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage()); | ||
595 | - } | ||
596 | - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | 682 | + } |
683 | + | ||
684 | + reportActivityInternal(sessionInfo); | ||
685 | + sendToDeviceActor(sessionInfo, msg, callback); | ||
686 | + } | ||
687 | + } | ||
688 | + | ||
689 | + @Override | ||
690 | + public void process( | ||
691 | + TransportProtos.SessionInfoProto sessionInfo, | ||
692 | + TransportProtos.PostTelemetryMsg msg, | ||
693 | + TransportServiceCallback<Void> callback) { | ||
694 | + int dataPoints = 0; | ||
695 | + for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { | ||
696 | + dataPoints += tsKv.getKvCount(); | ||
697 | + } | ||
698 | + if (checkLimits(sessionInfo, msg, callback, dataPoints)) { | ||
699 | + reportActivityInternal(sessionInfo); | ||
700 | + TenantId tenantId = getTenantId(sessionInfo); | ||
701 | + DeviceId deviceId = | ||
702 | + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
703 | + CustomerId customerId = getCustomerId(sessionInfo); | ||
704 | + MsgPackCallback packCallback = | ||
705 | + new MsgPackCallback( | ||
706 | + msg.getTsKvListCount(), | ||
707 | + new ApiStatsProxyCallback<>(tenantId, customerId, dataPoints, callback)); | ||
708 | + for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) { | ||
597 | TbMsgMetaData metaData = new TbMsgMetaData(); | 709 | TbMsgMetaData metaData = new TbMsgMetaData(); |
598 | - String selfData = FastIotConstants.YES; | ||
599 | - String eventDeviceId = eventInfo[0]; | ||
600 | - //通过设备名称或设备ID上报自己的事件 | ||
601 | - if(sessionInfo.getDeviceName().equals(eventInfo[0]) || eventDeviceId.equals(deviceId.toString())){ | ||
602 | - eventDeviceId = deviceId.toString(); | ||
603 | - }else{ | ||
604 | - //网关上报网关子设备的事件 | ||
605 | - selfData = FastIotConstants.NO; | ||
606 | - } | ||
607 | - reportActivityInternal(sessionInfo); | ||
608 | - JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); | ||
609 | - json.addProperty(EVENT_IDENTIFIER,eventInfo[1]); | ||
610 | - CustomerId customerId = getCustomerId(sessionInfo); | ||
611 | - TenantId tenantId = getTenantId(sessionInfo); | ||
612 | metaData.putValue("deviceName", sessionInfo.getDeviceName()); | 710 | metaData.putValue("deviceName", sessionInfo.getDeviceName()); |
613 | metaData.putValue("deviceType", sessionInfo.getDeviceType()); | 711 | metaData.putValue("deviceType", sessionInfo.getDeviceType()); |
614 | - metaData.putValue("deviceId",eventDeviceId); | ||
615 | - metaData.putValue(EVENT_IDENTIFIER, eventInfo[1]); | ||
616 | - metaData.putValue("selfData",selfData); | ||
617 | - sendToRuleEngine(tenantId, deviceId, customerId, sessionInfo, json, metaData, SessionMsgType.POST_EVENT_REQUEST, | ||
618 | - new TransportTbQueueCallback(new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback))); | ||
619 | - } | ||
620 | - | ||
621 | - @Override | ||
622 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback) { | ||
623 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
624 | - reportActivityInternal(sessionInfo); | ||
625 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo) | ||
626 | - .setGetAttributes(msg).build(), new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | 712 | + metaData.putValue("ts", tsKv.getTs() + ""); |
713 | + JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList()); | ||
714 | + sendToRuleEngine( | ||
715 | + tenantId, | ||
716 | + deviceId, | ||
717 | + customerId, | ||
718 | + sessionInfo, | ||
719 | + json, | ||
720 | + metaData, | ||
721 | + SessionMsgType.POST_TELEMETRY_REQUEST, | ||
722 | + packCallback); | ||
723 | + } | ||
724 | + } | ||
725 | + } | ||
726 | + | ||
727 | + @Override | ||
728 | + public void process( | ||
729 | + TransportProtos.SessionInfoProto sessionInfo, | ||
730 | + TransportProtos.PostAttributeMsg msg, | ||
731 | + TransportServiceCallback<Void> callback) { | ||
732 | + if (checkLimits(sessionInfo, msg, callback, msg.getKvCount())) { | ||
733 | + reportActivityInternal(sessionInfo); | ||
734 | + TenantId tenantId = getTenantId(sessionInfo); | ||
735 | + DeviceId deviceId = | ||
736 | + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
737 | + JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); | ||
738 | + TbMsgMetaData metaData = new TbMsgMetaData(); | ||
739 | + metaData.putValue("deviceName", sessionInfo.getDeviceName()); | ||
740 | + metaData.putValue("deviceType", sessionInfo.getDeviceType()); | ||
741 | + metaData.putValue("notifyDevice", "false"); | ||
742 | + CustomerId customerId = getCustomerId(sessionInfo); | ||
743 | + sendToRuleEngine( | ||
744 | + tenantId, | ||
745 | + deviceId, | ||
746 | + customerId, | ||
747 | + sessionInfo, | ||
748 | + json, | ||
749 | + metaData, | ||
750 | + SessionMsgType.POST_ATTRIBUTES_REQUEST, | ||
751 | + new TransportTbQueueCallback( | ||
752 | + new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback))); | ||
753 | + } | ||
754 | + } | ||
755 | + | ||
756 | + // thingskit | ||
757 | + @Override | ||
758 | + public void process( | ||
759 | + TransportProtos.SessionInfoProto sessionInfo, | ||
760 | + TransportProtos.PostEventMsg msg, | ||
761 | + TransportServiceCallback<Void> callback, | ||
762 | + String topicName) { | ||
763 | + // Topic地址:v1/devices/event/${deviceIdentifier}/${identifier} | ||
764 | + // ${deviceIdentifier} 标识支持deviceId/deviceName即SN | ||
765 | + String[] topicInfo = topicName.split(MqttTopics.BASE_DEVICE_EVENT_TOPIC + "/"); | ||
766 | + if (null == topicInfo || topicInfo.length != 2) { | ||
767 | + throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage()); | ||
768 | + } | ||
769 | + String[] eventInfo = topicInfo[1].split("/"); | ||
770 | + if (null == eventInfo || eventInfo.length != 2) { | ||
771 | + throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage()); | ||
772 | + } | ||
773 | + DeviceId deviceId = | ||
774 | + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
775 | + TbMsgMetaData metaData = new TbMsgMetaData(); | ||
776 | + String selfData = FastIotConstants.YES; | ||
777 | + String eventDeviceId = eventInfo[0]; | ||
778 | + // 通过设备名称或设备ID上报自己的事件 | ||
779 | + if (sessionInfo.getDeviceName().equals(eventInfo[0]) | ||
780 | + || eventDeviceId.equals(deviceId.toString())) { | ||
781 | + eventDeviceId = deviceId.toString(); | ||
782 | + } else { | ||
783 | + // 网关上报网关子设备的事件 | ||
784 | + selfData = FastIotConstants.NO; | ||
785 | + } | ||
786 | + reportActivityInternal(sessionInfo); | ||
787 | + JsonObject json = JsonUtils.getJsonObject(msg.getKvList()); | ||
788 | + json.addProperty(EVENT_IDENTIFIER, eventInfo[1]); | ||
789 | + CustomerId customerId = getCustomerId(sessionInfo); | ||
790 | + TenantId tenantId = getTenantId(sessionInfo); | ||
791 | + metaData.putValue("deviceName", sessionInfo.getDeviceName()); | ||
792 | + metaData.putValue("deviceType", sessionInfo.getDeviceType()); | ||
793 | + metaData.putValue("deviceId", eventDeviceId); | ||
794 | + metaData.putValue(EVENT_IDENTIFIER, eventInfo[1]); | ||
795 | + metaData.putValue("selfData", selfData); | ||
796 | + sendToRuleEngine( | ||
797 | + tenantId, | ||
798 | + deviceId, | ||
799 | + customerId, | ||
800 | + sessionInfo, | ||
801 | + json, | ||
802 | + metaData, | ||
803 | + SessionMsgType.POST_EVENT_REQUEST, | ||
804 | + new TransportTbQueueCallback( | ||
805 | + new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback))); | ||
806 | + } | ||
807 | + | ||
808 | + @Override | ||
809 | + public void process( | ||
810 | + TransportProtos.SessionInfoProto sessionInfo, | ||
811 | + TransportProtos.GetAttributeRequestMsg msg, | ||
812 | + TransportServiceCallback<Void> callback) { | ||
813 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
814 | + reportActivityInternal(sessionInfo); | ||
815 | + sendToDeviceActor( | ||
816 | + sessionInfo, | ||
817 | + TransportToDeviceActorMsg.newBuilder() | ||
818 | + .setSessionInfo(sessionInfo) | ||
819 | + .setGetAttributes(msg) | ||
820 | + .build(), | ||
821 | + new ApiStatsProxyCallback<>( | ||
822 | + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | ||
823 | + } | ||
824 | + } | ||
825 | + | ||
826 | + @Override | ||
827 | + public void process( | ||
828 | + TransportProtos.SessionInfoProto sessionInfo, | ||
829 | + TransportProtos.SubscribeToAttributeUpdatesMsg msg, | ||
830 | + TransportServiceCallback<Void> callback) { | ||
831 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
832 | + SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo)); | ||
833 | + if (sessionMetaData != null) { | ||
834 | + sessionMetaData.setSubscribedToAttributes(!msg.getUnsubscribe()); | ||
835 | + } | ||
836 | + reportActivityInternal(sessionInfo); | ||
837 | + sendToDeviceActor( | ||
838 | + sessionInfo, | ||
839 | + TransportToDeviceActorMsg.newBuilder() | ||
840 | + .setSessionInfo(sessionInfo) | ||
841 | + .setSubscribeToAttributes(msg) | ||
842 | + .build(), | ||
843 | + new ApiStatsProxyCallback<>( | ||
844 | + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | ||
845 | + } | ||
846 | + } | ||
847 | + | ||
848 | + @Override | ||
849 | + public void process( | ||
850 | + TransportProtos.SessionInfoProto sessionInfo, | ||
851 | + TransportProtos.SubscribeToRPCMsg msg, | ||
852 | + TransportServiceCallback<Void> callback) { | ||
853 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
854 | + SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo)); | ||
855 | + if (sessionMetaData != null) { | ||
856 | + sessionMetaData.setSubscribedToRPC(!msg.getUnsubscribe()); | ||
857 | + } | ||
858 | + reportActivityInternal(sessionInfo); | ||
859 | + sendToDeviceActor( | ||
860 | + sessionInfo, | ||
861 | + TransportToDeviceActorMsg.newBuilder() | ||
862 | + .setSessionInfo(sessionInfo) | ||
863 | + .setSubscribeToRPC(msg) | ||
864 | + .build(), | ||
865 | + new ApiStatsProxyCallback<>( | ||
866 | + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | ||
867 | + } | ||
868 | + } | ||
869 | + | ||
870 | + @Override | ||
871 | + public void process( | ||
872 | + TransportProtos.SessionInfoProto sessionInfo, | ||
873 | + TransportProtos.ToDeviceRpcResponseMsg msg, | ||
874 | + TransportServiceCallback<Void> callback) { | ||
875 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
876 | + reportActivityInternal(sessionInfo); | ||
877 | + sendToDeviceActor( | ||
878 | + sessionInfo, | ||
879 | + TransportToDeviceActorMsg.newBuilder() | ||
880 | + .setSessionInfo(sessionInfo) | ||
881 | + .setToDeviceRPCCallResponse(msg) | ||
882 | + .build(), | ||
883 | + new ApiStatsProxyCallback<>( | ||
884 | + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | ||
885 | + } | ||
886 | + } | ||
887 | + | ||
888 | + @Override | ||
889 | + public void notifyAboutUplink( | ||
890 | + TransportProtos.SessionInfoProto sessionInfo, | ||
891 | + TransportProtos.UplinkNotificationMsg msg, | ||
892 | + TransportServiceCallback<Void> callback) { | ||
893 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
894 | + reportActivityInternal(sessionInfo); | ||
895 | + sendToDeviceActor( | ||
896 | + sessionInfo, | ||
897 | + TransportToDeviceActorMsg.newBuilder() | ||
898 | + .setSessionInfo(sessionInfo) | ||
899 | + .setUplinkNotificationMsg(msg) | ||
900 | + .build(), | ||
901 | + callback); | ||
902 | + } | ||
903 | + } | ||
904 | + | ||
905 | + @Override | ||
906 | + public void process( | ||
907 | + TransportProtos.SessionInfoProto sessionInfo, | ||
908 | + TransportProtos.ToDeviceRpcRequestMsg msg, | ||
909 | + RpcStatus rpcStatus, | ||
910 | + TransportServiceCallback<Void> callback) { | ||
911 | + TransportProtos.ToDeviceRpcResponseStatusMsg responseMsg = | ||
912 | + TransportProtos.ToDeviceRpcResponseStatusMsg.newBuilder() | ||
913 | + .setRequestId(msg.getRequestId()) | ||
914 | + .setRequestIdLSB(msg.getRequestIdLSB()) | ||
915 | + .setRequestIdMSB(msg.getRequestIdMSB()) | ||
916 | + .setStatus(rpcStatus.name()) | ||
917 | + .build(); | ||
918 | + | ||
919 | + if (checkLimits(sessionInfo, responseMsg, callback)) { | ||
920 | + reportActivityInternal(sessionInfo); | ||
921 | + sendToDeviceActor( | ||
922 | + sessionInfo, | ||
923 | + TransportToDeviceActorMsg.newBuilder() | ||
924 | + .setSessionInfo(sessionInfo) | ||
925 | + .setRpcResponseStatusMsg(responseMsg) | ||
926 | + .build(), | ||
927 | + new ApiStatsProxyCallback<>( | ||
928 | + getTenantId(sessionInfo), | ||
929 | + getCustomerId(sessionInfo), | ||
930 | + 1, | ||
931 | + TransportServiceCallback.EMPTY)); | ||
932 | + } | ||
933 | + } | ||
934 | + | ||
935 | + private void processTimeout(String requestId) { | ||
936 | + RpcRequestMetadata data = toServerRpcPendingMap.remove(requestId); | ||
937 | + if (data != null) { | ||
938 | + SessionMetaData md = sessions.get(data.getSessionId()); | ||
939 | + if (md != null) { | ||
940 | + SessionMsgListener listener = md.getListener(); | ||
941 | + transportCallbackExecutor.submit( | ||
942 | + () -> { | ||
943 | + TransportProtos.ToServerRpcResponseMsg responseMsg = | ||
944 | + TransportProtos.ToServerRpcResponseMsg.newBuilder() | ||
945 | + .setRequestId(data.getRequestId()) | ||
946 | + .setError("timeout") | ||
947 | + .build(); | ||
948 | + listener.onToServerRpcResponse(responseMsg); | ||
949 | + }); | ||
950 | + if (md.getSessionType() == TransportProtos.SessionType.SYNC) { | ||
951 | + deregisterSession(md.getSessionInfo()); | ||
627 | } | 952 | } |
628 | - } | ||
629 | - | ||
630 | - @Override | ||
631 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback) { | ||
632 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
633 | - SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo)); | ||
634 | - if (sessionMetaData != null) { | ||
635 | - sessionMetaData.setSubscribedToAttributes(!msg.getUnsubscribe()); | 953 | + } else { |
954 | + log.debug("[{}] Missing session.", data.getSessionId()); | ||
955 | + } | ||
956 | + } | ||
957 | + } | ||
958 | + | ||
959 | + @Override | ||
960 | + public void process( | ||
961 | + TransportProtos.SessionInfoProto sessionInfo, | ||
962 | + TransportProtos.ToServerRpcRequestMsg msg, | ||
963 | + TransportServiceCallback<Void> callback) { | ||
964 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
965 | + reportActivityInternal(sessionInfo); | ||
966 | + UUID sessionId = toSessionId(sessionInfo); | ||
967 | + TenantId tenantId = getTenantId(sessionInfo); | ||
968 | + DeviceId deviceId = getDeviceId(sessionInfo); | ||
969 | + JsonObject json = new JsonObject(); | ||
970 | + json.addProperty("method", msg.getMethodName()); | ||
971 | + json.add("params", JsonUtils.parse(msg.getParams())); | ||
972 | + | ||
973 | + TbMsgMetaData metaData = new TbMsgMetaData(); | ||
974 | + metaData.putValue("deviceName", sessionInfo.getDeviceName()); | ||
975 | + metaData.putValue("deviceType", sessionInfo.getDeviceType()); | ||
976 | + metaData.putValue("requestId", Integer.toString(msg.getRequestId())); | ||
977 | + metaData.putValue("serviceId", serviceInfoProvider.getServiceId()); | ||
978 | + metaData.putValue("sessionId", sessionId.toString()); | ||
979 | + sendToRuleEngine( | ||
980 | + tenantId, | ||
981 | + deviceId, | ||
982 | + getCustomerId(sessionInfo), | ||
983 | + sessionInfo, | ||
984 | + json, | ||
985 | + metaData, | ||
986 | + SessionMsgType.TO_SERVER_RPC_REQUEST, | ||
987 | + new TransportTbQueueCallback(callback)); | ||
988 | + String requestId = sessionId + "-" + msg.getRequestId(); | ||
989 | + toServerRpcPendingMap.put(requestId, new RpcRequestMetadata(sessionId, msg.getRequestId())); | ||
990 | + scheduler.schedule( | ||
991 | + () -> processTimeout(requestId), clientSideRpcTimeout, TimeUnit.MILLISECONDS); | ||
992 | + } | ||
993 | + } | ||
994 | + | ||
995 | + @Override | ||
996 | + public void process( | ||
997 | + TransportProtos.SessionInfoProto sessionInfo, | ||
998 | + TransportProtos.ClaimDeviceMsg msg, | ||
999 | + TransportServiceCallback<Void> callback) { | ||
1000 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
1001 | + reportActivityInternal(sessionInfo); | ||
1002 | + sendToDeviceActor( | ||
1003 | + sessionInfo, | ||
1004 | + TransportToDeviceActorMsg.newBuilder() | ||
1005 | + .setSessionInfo(sessionInfo) | ||
1006 | + .setClaimDevice(msg) | ||
1007 | + .build(), | ||
1008 | + callback); | ||
1009 | + } | ||
1010 | + } | ||
1011 | + | ||
1012 | + @Override | ||
1013 | + public void process( | ||
1014 | + TransportProtos.SessionInfoProto sessionInfo, | ||
1015 | + TransportProtos.GetOtaPackageRequestMsg msg, | ||
1016 | + TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> callback) { | ||
1017 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
1018 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
1019 | + new TbProtoQueueMsg<>( | ||
1020 | + UUID.randomUUID(), | ||
1021 | + TransportApiRequestMsg.newBuilder().setOtaPackageRequestMsg(msg).build()); | ||
1022 | + | ||
1023 | + AsyncCallbackTemplate.withCallback( | ||
1024 | + transportApiRequestTemplate.send(protoMsg), | ||
1025 | + response -> { | ||
1026 | + callback.onSuccess(response.getValue().getOtaPackageResponseMsg()); | ||
1027 | + }, | ||
1028 | + callback::onError, | ||
1029 | + transportCallbackExecutor); | ||
1030 | + } | ||
1031 | + } | ||
1032 | + | ||
1033 | + @Override | ||
1034 | + public void reportActivity(TransportProtos.SessionInfoProto sessionInfo) { | ||
1035 | + reportActivityInternal(sessionInfo); | ||
1036 | + } | ||
1037 | + | ||
1038 | + private void reportActivityInternal(TransportProtos.SessionInfoProto sessionInfo) { | ||
1039 | + UUID sessionId = toSessionId(sessionInfo); | ||
1040 | + SessionActivityData sessionMetaData = | ||
1041 | + sessionsActivity.computeIfAbsent(sessionId, id -> new SessionActivityData(sessionInfo)); | ||
1042 | + sessionMetaData.updateLastActivityTime(); | ||
1043 | + } | ||
1044 | + | ||
1045 | + private void checkInactivityAndReportActivity() { | ||
1046 | + long expTime = System.currentTimeMillis() - sessionInactivityTimeout; | ||
1047 | + Set<UUID> sessionsToRemove = new HashSet<>(); | ||
1048 | + sessionsActivity.forEach( | ||
1049 | + (uuid, sessionAD) -> { | ||
1050 | + long lastActivityTime = sessionAD.getLastActivityTime(); | ||
1051 | + SessionMetaData sessionMD = sessions.get(uuid); | ||
1052 | + if (sessionMD != null) { | ||
1053 | + sessionAD.setSessionInfo(sessionMD.getSessionInfo()); | ||
1054 | + } else { | ||
1055 | + sessionsToRemove.add(uuid); | ||
1056 | + } | ||
1057 | + TransportProtos.SessionInfoProto sessionInfo = sessionAD.getSessionInfo(); | ||
1058 | + | ||
1059 | + if (sessionInfo.getGwSessionIdMSB() != 0 && sessionInfo.getGwSessionIdLSB() != 0) { | ||
1060 | + var gwSessionId = | ||
1061 | + new UUID(sessionInfo.getGwSessionIdMSB(), sessionInfo.getGwSessionIdLSB()); | ||
1062 | + SessionMetaData gwMetaData = sessions.get(gwSessionId); | ||
1063 | + SessionActivityData gwActivityData = sessionsActivity.get(gwSessionId); | ||
1064 | + if (gwMetaData != null && gwMetaData.isOverwriteActivityTime()) { | ||
1065 | + lastActivityTime = Math.max(gwActivityData.getLastActivityTime(), lastActivityTime); | ||
636 | } | 1066 | } |
637 | - reportActivityInternal(sessionInfo); | ||
638 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSubscribeToAttributes(msg).build(), | ||
639 | - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | ||
640 | - } | ||
641 | - } | ||
642 | - | ||
643 | - @Override | ||
644 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback) { | ||
645 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
646 | - SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo)); | ||
647 | - if (sessionMetaData != null) { | ||
648 | - sessionMetaData.setSubscribedToRPC(!msg.getUnsubscribe()); | 1067 | + } |
1068 | + if (lastActivityTime < expTime) { | ||
1069 | + if (sessionMD != null) { | ||
1070 | + if (log.isDebugEnabled()) { | ||
1071 | + log.debug( | ||
1072 | + "[{}] Session has expired due to last activity time: {}", | ||
1073 | + toSessionId(sessionInfo), | ||
1074 | + lastActivityTime); | ||
1075 | + } | ||
1076 | + sessions.remove(uuid); | ||
1077 | + sessionsToRemove.add(uuid); | ||
1078 | + process(sessionInfo, SESSION_EVENT_MSG_CLOSED, null); | ||
1079 | + sessionMD | ||
1080 | + .getListener() | ||
1081 | + .onRemoteSessionCloseCommand(uuid, SESSION_CLOSE_NOTIFICATION_PROTO); | ||
649 | } | 1082 | } |
650 | - reportActivityInternal(sessionInfo); | ||
651 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSubscribeToRPC(msg).build(), | ||
652 | - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | ||
653 | - } | ||
654 | - } | ||
655 | - | ||
656 | - @Override | ||
657 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback) { | ||
658 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
659 | - reportActivityInternal(sessionInfo); | ||
660 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setToDeviceRPCCallResponse(msg).build(), | ||
661 | - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); | ||
662 | - } | ||
663 | - } | ||
664 | - | ||
665 | - @Override | ||
666 | - public void notifyAboutUplink(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.UplinkNotificationMsg msg, TransportServiceCallback<Void> callback) { | ||
667 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
668 | - reportActivityInternal(sessionInfo); | ||
669 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setUplinkNotificationMsg(msg).build(), callback); | ||
670 | - } | ||
671 | - } | ||
672 | - | ||
673 | - @Override | ||
674 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback) { | ||
675 | - TransportProtos.ToDeviceRpcResponseStatusMsg responseMsg = TransportProtos.ToDeviceRpcResponseStatusMsg.newBuilder() | ||
676 | - .setRequestId(msg.getRequestId()) | ||
677 | - .setRequestIdLSB(msg.getRequestIdLSB()) | ||
678 | - .setRequestIdMSB(msg.getRequestIdMSB()) | ||
679 | - .setStatus(rpcStatus.name()) | ||
680 | - .build(); | ||
681 | - | ||
682 | - if (checkLimits(sessionInfo, responseMsg, callback)) { | ||
683 | - reportActivityInternal(sessionInfo); | ||
684 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setRpcResponseStatusMsg(responseMsg).build(), | ||
685 | - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY)); | ||
686 | - } | ||
687 | - } | 1083 | + } else { |
1084 | + if (lastActivityTime > sessionAD.getLastReportedActivityTime()) { | ||
1085 | + final long lastActivityTimeFinal = lastActivityTime; | ||
1086 | + process( | ||
1087 | + sessionInfo, | ||
1088 | + TransportProtos.SubscriptionInfoProto.newBuilder() | ||
1089 | + .setAttributeSubscription( | ||
1090 | + sessionMD != null && sessionMD.isSubscribedToAttributes()) | ||
1091 | + .setRpcSubscription(sessionMD != null && sessionMD.isSubscribedToRPC()) | ||
1092 | + .setLastActivityTime(lastActivityTime) | ||
1093 | + .build(), | ||
1094 | + new TransportServiceCallback<Void>() { | ||
1095 | + @Override | ||
1096 | + public void onSuccess(Void msg) { | ||
1097 | + sessionAD.setLastReportedActivityTime(lastActivityTimeFinal); | ||
1098 | + } | ||
688 | 1099 | ||
689 | - private void processTimeout(String requestId) { | ||
690 | - RpcRequestMetadata data = toServerRpcPendingMap.remove(requestId); | ||
691 | - if (data != null) { | ||
692 | - SessionMetaData md = sessions.get(data.getSessionId()); | ||
693 | - if (md != null) { | ||
694 | - SessionMsgListener listener = md.getListener(); | ||
695 | - transportCallbackExecutor.submit(() -> { | ||
696 | - TransportProtos.ToServerRpcResponseMsg responseMsg = | ||
697 | - TransportProtos.ToServerRpcResponseMsg.newBuilder() | ||
698 | - .setRequestId(data.getRequestId()) | ||
699 | - .setError("timeout").build(); | ||
700 | - listener.onToServerRpcResponse(responseMsg); | ||
701 | - }); | ||
702 | - if (md.getSessionType() == TransportProtos.SessionType.SYNC) { | ||
703 | - deregisterSession(md.getSessionInfo()); | ||
704 | - } | ||
705 | - } else { | ||
706 | - log.debug("[{}] Missing session.", data.getSessionId()); | 1100 | + @Override |
1101 | + public void onError(Throwable e) { | ||
1102 | + log.warn("[{}] Failed to report last activity time", uuid, e); | ||
1103 | + } | ||
1104 | + }); | ||
707 | } | 1105 | } |
708 | - } | ||
709 | - } | ||
710 | - | ||
711 | - @Override | ||
712 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback) { | ||
713 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
714 | - reportActivityInternal(sessionInfo); | ||
715 | - UUID sessionId = toSessionId(sessionInfo); | ||
716 | - TenantId tenantId = getTenantId(sessionInfo); | ||
717 | - DeviceId deviceId = getDeviceId(sessionInfo); | ||
718 | - JsonObject json = new JsonObject(); | ||
719 | - json.addProperty("method", msg.getMethodName()); | ||
720 | - json.add("params", JsonUtils.parse(msg.getParams())); | ||
721 | - | ||
722 | - TbMsgMetaData metaData = new TbMsgMetaData(); | ||
723 | - metaData.putValue("deviceName", sessionInfo.getDeviceName()); | ||
724 | - metaData.putValue("deviceType", sessionInfo.getDeviceType()); | ||
725 | - metaData.putValue("requestId", Integer.toString(msg.getRequestId())); | ||
726 | - metaData.putValue("serviceId", serviceInfoProvider.getServiceId()); | ||
727 | - metaData.putValue("sessionId", sessionId.toString()); | ||
728 | - sendToRuleEngine(tenantId, deviceId, getCustomerId(sessionInfo), sessionInfo, json, metaData, | ||
729 | - SessionMsgType.TO_SERVER_RPC_REQUEST, new TransportTbQueueCallback(callback)); | ||
730 | - String requestId = sessionId + "-" + msg.getRequestId(); | ||
731 | - toServerRpcPendingMap.put(requestId, new RpcRequestMetadata(sessionId, msg.getRequestId())); | ||
732 | - scheduler.schedule(() -> processTimeout(requestId), clientSideRpcTimeout, TimeUnit.MILLISECONDS); | ||
733 | - } | ||
734 | - } | ||
735 | - | ||
736 | - @Override | ||
737 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ClaimDeviceMsg msg, TransportServiceCallback<Void> callback) { | ||
738 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
739 | - reportActivityInternal(sessionInfo); | ||
740 | - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo) | ||
741 | - .setClaimDevice(msg).build(), callback); | ||
742 | - } | ||
743 | - } | ||
744 | - | ||
745 | - @Override | ||
746 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.GetOtaPackageRequestMsg msg, TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> callback) { | ||
747 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
748 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
749 | - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setOtaPackageRequestMsg(msg).build()); | ||
750 | - | ||
751 | - AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), response -> { | ||
752 | - callback.onSuccess(response.getValue().getOtaPackageResponseMsg()); | ||
753 | - }, callback::onError, transportCallbackExecutor); | ||
754 | - } | ||
755 | - } | ||
756 | - | ||
757 | - @Override | ||
758 | - public void reportActivity(TransportProtos.SessionInfoProto sessionInfo) { | ||
759 | - reportActivityInternal(sessionInfo); | ||
760 | - } | ||
761 | - | ||
762 | - private void reportActivityInternal(TransportProtos.SessionInfoProto sessionInfo) { | ||
763 | - UUID sessionId = toSessionId(sessionInfo); | ||
764 | - SessionActivityData sessionMetaData = sessionsActivity.computeIfAbsent(sessionId, id -> new SessionActivityData(sessionInfo)); | ||
765 | - sessionMetaData.updateLastActivityTime(); | ||
766 | - } | ||
767 | - | ||
768 | - private void checkInactivityAndReportActivity() { | ||
769 | - long expTime = System.currentTimeMillis() - sessionInactivityTimeout; | ||
770 | - Set<UUID> sessionsToRemove = new HashSet<>(); | ||
771 | - sessionsActivity.forEach((uuid, sessionAD) -> { | ||
772 | - long lastActivityTime = sessionAD.getLastActivityTime(); | ||
773 | - SessionMetaData sessionMD = sessions.get(uuid); | ||
774 | - if (sessionMD != null) { | ||
775 | - sessionAD.setSessionInfo(sessionMD.getSessionInfo()); | ||
776 | - } else { | ||
777 | - sessionsToRemove.add(uuid); | 1106 | + } |
1107 | + }); | ||
1108 | + // Removes all closed or short-lived sessions. | ||
1109 | + sessionsToRemove.forEach(sessionsActivity::remove); | ||
1110 | + } | ||
1111 | + | ||
1112 | + @Override | ||
1113 | + public SessionMetaData registerSyncSession( | ||
1114 | + TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout) { | ||
1115 | + SessionMetaData currentSession = | ||
1116 | + new SessionMetaData(sessionInfo, TransportProtos.SessionType.SYNC, listener); | ||
1117 | + UUID sessionId = toSessionId(sessionInfo); | ||
1118 | + sessions.putIfAbsent(sessionId, currentSession); | ||
1119 | + | ||
1120 | + TransportProtos.SessionCloseNotificationProto notification = | ||
1121 | + TransportProtos.SessionCloseNotificationProto.newBuilder() | ||
1122 | + .setMessage("session timeout!") | ||
1123 | + .build(); | ||
1124 | + | ||
1125 | + ScheduledFuture executorFuture = | ||
1126 | + scheduler.schedule( | ||
1127 | + () -> { | ||
1128 | + listener.onRemoteSessionCloseCommand(sessionId, notification); | ||
1129 | + deregisterSession(sessionInfo); | ||
1130 | + }, | ||
1131 | + timeout, | ||
1132 | + TimeUnit.MILLISECONDS); | ||
1133 | + | ||
1134 | + currentSession.setScheduledFuture(executorFuture); | ||
1135 | + return currentSession; | ||
1136 | + } | ||
1137 | + | ||
1138 | + @Override | ||
1139 | + public void deregisterSession(TransportProtos.SessionInfoProto sessionInfo) { | ||
1140 | + SessionMetaData currentSession = sessions.get(toSessionId(sessionInfo)); | ||
1141 | + if (currentSession != null && currentSession.hasScheduledFuture()) { | ||
1142 | + log.debug("Stopping scheduler to avoid resending response if request has been ack."); | ||
1143 | + currentSession.getScheduledFuture().cancel(false); | ||
1144 | + } | ||
1145 | + sessions.remove(toSessionId(sessionInfo)); | ||
1146 | + } | ||
1147 | + | ||
1148 | + @Override | ||
1149 | + public void log(TransportProtos.SessionInfoProto sessionInfo, String msg) { | ||
1150 | + if (!logEnabled || sessionInfo == null || StringUtils.isEmpty(msg)) { | ||
1151 | + return; | ||
1152 | + } | ||
1153 | + if (msg.length() > logMaxLength) { | ||
1154 | + msg = msg.substring(0, logMaxLength); | ||
1155 | + } | ||
1156 | + TransportProtos.PostTelemetryMsg.Builder request = | ||
1157 | + TransportProtos.PostTelemetryMsg.newBuilder(); | ||
1158 | + TransportProtos.TsKvListProto.Builder builder = TransportProtos.TsKvListProto.newBuilder(); | ||
1159 | + builder.setTs( | ||
1160 | + TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L | ||
1161 | + + (atomicTs.getAndIncrement() % 1000)); | ||
1162 | + builder.addKv( | ||
1163 | + TransportProtos.KeyValueProto.newBuilder() | ||
1164 | + .setKey("transportLog") | ||
1165 | + .setType(TransportProtos.KeyValueType.STRING_V) | ||
1166 | + .setStringV(msg) | ||
1167 | + .build()); | ||
1168 | + request.addTsKvList(builder.build()); | ||
1169 | + TransportProtos.PostTelemetryMsg postTelemetryMsg = request.build(); | ||
1170 | + process(sessionInfo, postTelemetryMsg, TransportServiceCallback.EMPTY); | ||
1171 | + } | ||
1172 | + | ||
1173 | + private boolean checkLimits( | ||
1174 | + TransportProtos.SessionInfoProto sessionInfo, | ||
1175 | + Object msg, | ||
1176 | + TransportServiceCallback<?> callback) { | ||
1177 | + return checkLimits(sessionInfo, msg, callback, 0); | ||
1178 | + } | ||
1179 | + | ||
1180 | + private boolean checkLimits( | ||
1181 | + TransportProtos.SessionInfoProto sessionInfo, | ||
1182 | + Object msg, | ||
1183 | + TransportServiceCallback<?> callback, | ||
1184 | + int dataPoints) { | ||
1185 | + if (log.isTraceEnabled()) { | ||
1186 | + log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg); | ||
1187 | + } | ||
1188 | + TenantId tenantId = | ||
1189 | + TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB())); | ||
1190 | + DeviceId deviceId = | ||
1191 | + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
1192 | + | ||
1193 | + EntityType rateLimitedEntityType = rateLimitService.checkLimits(tenantId, deviceId, dataPoints); | ||
1194 | + if (rateLimitedEntityType == null) { | ||
1195 | + return true; | ||
1196 | + } else { | ||
1197 | + if (callback != null) { | ||
1198 | + callback.onError(new TbRateLimitsException(rateLimitedEntityType)); | ||
1199 | + } | ||
1200 | + return false; | ||
1201 | + } | ||
1202 | + } | ||
1203 | + | ||
1204 | + protected void processToTransportMsg(ToTransportMsg toSessionMsg) { | ||
1205 | + UUID sessionId = new UUID(toSessionMsg.getSessionIdMSB(), toSessionMsg.getSessionIdLSB()); | ||
1206 | + SessionMetaData md = sessions.get(sessionId); | ||
1207 | + if (md != null) { | ||
1208 | + log.trace("[{}] Processing notification: {}", sessionId, toSessionMsg); | ||
1209 | + SessionMsgListener listener = md.getListener(); | ||
1210 | + transportCallbackExecutor.submit( | ||
1211 | + () -> { | ||
1212 | + if (toSessionMsg.hasGetAttributesResponse()) { | ||
1213 | + listener.onGetAttributesResponse(toSessionMsg.getGetAttributesResponse()); | ||
778 | } | 1214 | } |
779 | - TransportProtos.SessionInfoProto sessionInfo = sessionAD.getSessionInfo(); | ||
780 | - | ||
781 | - if (sessionInfo.getGwSessionIdMSB() != 0 && sessionInfo.getGwSessionIdLSB() != 0) { | ||
782 | - var gwSessionId = new UUID(sessionInfo.getGwSessionIdMSB(), sessionInfo.getGwSessionIdLSB()); | ||
783 | - SessionMetaData gwMetaData = sessions.get(gwSessionId); | ||
784 | - SessionActivityData gwActivityData = sessionsActivity.get(gwSessionId); | ||
785 | - if (gwMetaData != null && gwMetaData.isOverwriteActivityTime()) { | ||
786 | - lastActivityTime = Math.max(gwActivityData.getLastActivityTime(), lastActivityTime); | ||
787 | - } | 1215 | + if (toSessionMsg.hasAttributeUpdateNotification()) { |
1216 | + listener.onAttributeUpdate(sessionId, toSessionMsg.getAttributeUpdateNotification()); | ||
788 | } | 1217 | } |
789 | - if (lastActivityTime < expTime) { | ||
790 | - if (sessionMD != null) { | ||
791 | - if (log.isDebugEnabled()) { | ||
792 | - log.debug("[{}] Session has expired due to last activity time: {}", toSessionId(sessionInfo), lastActivityTime); | ||
793 | - } | ||
794 | - sessions.remove(uuid); | ||
795 | - sessionsToRemove.add(uuid); | ||
796 | - process(sessionInfo, SESSION_EVENT_MSG_CLOSED, null); | ||
797 | - sessionMD.getListener().onRemoteSessionCloseCommand(uuid, SESSION_CLOSE_NOTIFICATION_PROTO); | ||
798 | - } | ||
799 | - } else { | ||
800 | - if (lastActivityTime > sessionAD.getLastReportedActivityTime()) { | ||
801 | - final long lastActivityTimeFinal = lastActivityTime; | ||
802 | - process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder() | ||
803 | - .setAttributeSubscription(sessionMD != null && sessionMD.isSubscribedToAttributes()) | ||
804 | - .setRpcSubscription(sessionMD != null && sessionMD.isSubscribedToRPC()) | ||
805 | - .setLastActivityTime(lastActivityTime).build(), new TransportServiceCallback<Void>() { | ||
806 | - @Override | ||
807 | - public void onSuccess(Void msg) { | ||
808 | - sessionAD.setLastReportedActivityTime(lastActivityTimeFinal); | ||
809 | - } | ||
810 | - | ||
811 | - @Override | ||
812 | - public void onError(Throwable e) { | ||
813 | - log.warn("[{}] Failed to report last activity time", uuid, e); | ||
814 | - } | ||
815 | - }); | ||
816 | - } | 1218 | + if (toSessionMsg.hasSessionCloseNotification()) { |
1219 | + listener.onRemoteSessionCloseCommand( | ||
1220 | + sessionId, toSessionMsg.getSessionCloseNotification()); | ||
817 | } | 1221 | } |
818 | - }); | ||
819 | - // Removes all closed or short-lived sessions. | ||
820 | - sessionsToRemove.forEach(sessionsActivity::remove); | ||
821 | - } | ||
822 | - | ||
823 | - @Override | ||
824 | - public SessionMetaData registerSyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout) { | ||
825 | - SessionMetaData currentSession = new SessionMetaData(sessionInfo, TransportProtos.SessionType.SYNC, listener); | ||
826 | - UUID sessionId = toSessionId(sessionInfo); | ||
827 | - sessions.putIfAbsent(sessionId, currentSession); | ||
828 | - | ||
829 | - TransportProtos.SessionCloseNotificationProto notification = TransportProtos.SessionCloseNotificationProto.newBuilder().setMessage("session timeout!").build(); | ||
830 | - | ||
831 | - ScheduledFuture executorFuture = scheduler.schedule(() -> { | ||
832 | - listener.onRemoteSessionCloseCommand(sessionId, notification); | ||
833 | - deregisterSession(sessionInfo); | ||
834 | - }, timeout, TimeUnit.MILLISECONDS); | ||
835 | - | ||
836 | - currentSession.setScheduledFuture(executorFuture); | ||
837 | - return currentSession; | ||
838 | - } | ||
839 | - | ||
840 | - @Override | ||
841 | - public void deregisterSession(TransportProtos.SessionInfoProto sessionInfo) { | ||
842 | - SessionMetaData currentSession = sessions.get(toSessionId(sessionInfo)); | ||
843 | - if (currentSession != null && currentSession.hasScheduledFuture()) { | ||
844 | - log.debug("Stopping scheduler to avoid resending response if request has been ack."); | ||
845 | - currentSession.getScheduledFuture().cancel(false); | ||
846 | - } | ||
847 | - sessions.remove(toSessionId(sessionInfo)); | ||
848 | - } | ||
849 | - | ||
850 | - @Override | ||
851 | - public void log(TransportProtos.SessionInfoProto sessionInfo, String msg) { | ||
852 | - if (!logEnabled || sessionInfo == null || StringUtils.isEmpty(msg)) { | ||
853 | - return; | ||
854 | - } | ||
855 | - if (msg.length() > logMaxLength) { | ||
856 | - msg = msg.substring(0, logMaxLength); | ||
857 | - } | ||
858 | - TransportProtos.PostTelemetryMsg.Builder request = TransportProtos.PostTelemetryMsg.newBuilder(); | ||
859 | - TransportProtos.TsKvListProto.Builder builder = TransportProtos.TsKvListProto.newBuilder(); | ||
860 | - builder.setTs(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L + (atomicTs.getAndIncrement() % 1000)); | ||
861 | - builder.addKv(TransportProtos.KeyValueProto.newBuilder() | ||
862 | - .setKey("transportLog") | ||
863 | - .setType(TransportProtos.KeyValueType.STRING_V) | ||
864 | - .setStringV(msg).build()); | ||
865 | - request.addTsKvList(builder.build()); | ||
866 | - TransportProtos.PostTelemetryMsg postTelemetryMsg = request.build(); | ||
867 | - process(sessionInfo, postTelemetryMsg, TransportServiceCallback.EMPTY); | ||
868 | - } | ||
869 | - | ||
870 | - private boolean checkLimits(TransportProtos.SessionInfoProto sessionInfo, Object msg, TransportServiceCallback<?> callback) { | ||
871 | - return checkLimits(sessionInfo, msg, callback, 0); | ||
872 | - } | ||
873 | - | ||
874 | - private boolean checkLimits(TransportProtos.SessionInfoProto sessionInfo, Object msg, TransportServiceCallback<?> callback, int dataPoints) { | ||
875 | - if (log.isTraceEnabled()) { | ||
876 | - log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg); | ||
877 | - } | ||
878 | - TenantId tenantId = TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB())); | ||
879 | - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
880 | - | ||
881 | - EntityType rateLimitedEntityType = rateLimitService.checkLimits(tenantId, deviceId, dataPoints); | ||
882 | - if (rateLimitedEntityType == null) { | ||
883 | - return true; | ||
884 | - } else { | ||
885 | - if (callback != null) { | ||
886 | - callback.onError(new TbRateLimitsException(rateLimitedEntityType)); | 1222 | + if (toSessionMsg.hasToTransportUpdateCredentialsNotification()) { |
1223 | + listener.onToTransportUpdateCredentials( | ||
1224 | + toSessionMsg.getToTransportUpdateCredentialsNotification()); | ||
887 | } | 1225 | } |
888 | - return false; | ||
889 | - } | ||
890 | - } | ||
891 | - | ||
892 | - protected void processToTransportMsg(ToTransportMsg toSessionMsg) { | ||
893 | - UUID sessionId = new UUID(toSessionMsg.getSessionIdMSB(), toSessionMsg.getSessionIdLSB()); | ||
894 | - SessionMetaData md = sessions.get(sessionId); | ||
895 | - if (md != null) { | ||
896 | - log.trace("[{}] Processing notification: {}", sessionId, toSessionMsg); | ||
897 | - SessionMsgListener listener = md.getListener(); | ||
898 | - transportCallbackExecutor.submit(() -> { | ||
899 | - if (toSessionMsg.hasGetAttributesResponse()) { | ||
900 | - listener.onGetAttributesResponse(toSessionMsg.getGetAttributesResponse()); | ||
901 | - } | ||
902 | - if (toSessionMsg.hasAttributeUpdateNotification()) { | ||
903 | - listener.onAttributeUpdate(sessionId, toSessionMsg.getAttributeUpdateNotification()); | ||
904 | - } | ||
905 | - if (toSessionMsg.hasSessionCloseNotification()) { | ||
906 | - listener.onRemoteSessionCloseCommand(sessionId, toSessionMsg.getSessionCloseNotification()); | ||
907 | - } | ||
908 | - if (toSessionMsg.hasToTransportUpdateCredentialsNotification()) { | ||
909 | - listener.onToTransportUpdateCredentials(toSessionMsg.getToTransportUpdateCredentialsNotification()); | ||
910 | - } | ||
911 | - if (toSessionMsg.hasToDeviceRequest()) { | ||
912 | - listener.onToDeviceRpcRequest(sessionId, toSessionMsg.getToDeviceRequest()); | ||
913 | - } | ||
914 | - if (toSessionMsg.hasToServerResponse()) { | ||
915 | - String requestId = sessionId + "-" + toSessionMsg.getToServerResponse().getRequestId(); | ||
916 | - toServerRpcPendingMap.remove(requestId); | ||
917 | - listener.onToServerRpcResponse(toSessionMsg.getToServerResponse()); | ||
918 | - } | ||
919 | - }); | ||
920 | - if (md.getSessionType() == TransportProtos.SessionType.SYNC) { | ||
921 | - deregisterSession(md.getSessionInfo()); | 1226 | + if (toSessionMsg.hasToDeviceRequest()) { |
1227 | + listener.onToDeviceRpcRequest(sessionId, toSessionMsg.getToDeviceRequest()); | ||
922 | } | 1228 | } |
923 | - } else { | ||
924 | - log.trace("Processing broadcast notification: {}", toSessionMsg); | ||
925 | - if (toSessionMsg.hasEntityUpdateMsg()) { | ||
926 | - TransportProtos.EntityUpdateMsg msg = toSessionMsg.getEntityUpdateMsg(); | ||
927 | - EntityType entityType = EntityType.valueOf(msg.getEntityType()); | ||
928 | - if (EntityType.DEVICE_PROFILE.equals(entityType)) { | ||
929 | - DeviceProfile deviceProfile = deviceProfileCache.put(msg.getData()); | ||
930 | - if (deviceProfile != null) { | ||
931 | - log.info("On device profile update: {}", deviceProfile); | ||
932 | - onProfileUpdate(deviceProfile); | ||
933 | - } | ||
934 | - } else if (EntityType.TENANT_PROFILE.equals(entityType)) { | ||
935 | - rateLimitService.update(tenantProfileCache.put(msg.getData())); | ||
936 | - } else if (EntityType.TENANT.equals(entityType)) { | ||
937 | - Optional<Tenant> profileOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
938 | - if (profileOpt.isPresent()) { | ||
939 | - Tenant tenant = profileOpt.get(); | ||
940 | - boolean updated = tenantProfileCache.put(tenant.getId(), tenant.getTenantProfileId()); | ||
941 | - if (updated) { | ||
942 | - rateLimitService.update(tenant.getId()); | ||
943 | - } | ||
944 | - } | ||
945 | - } else if (EntityType.API_USAGE_STATE.equals(entityType)) { | ||
946 | - Optional<ApiUsageState> stateOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
947 | - if (stateOpt.isPresent()) { | ||
948 | - ApiUsageState apiUsageState = stateOpt.get(); | ||
949 | - rateLimitService.update(apiUsageState.getTenantId(), apiUsageState.isTransportEnabled()); | ||
950 | - //TODO: if transport is disabled, we should close all sessions and not to check credentials. | ||
951 | - } | ||
952 | - } else if (EntityType.DEVICE.equals(entityType)) { | ||
953 | - Optional<Device> deviceOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
954 | - deviceOpt.ifPresent(device -> { | ||
955 | - onDeviceUpdate(device); | ||
956 | - eventPublisher.publishEvent(new DeviceUpdatedEvent(device)); | ||
957 | - }); | ||
958 | - | ||
959 | - //Thingskit function | ||
960 | - } else if (EntityType.JS_SCRIPT.equals(entityType)) { | ||
961 | - Optional<TkDeviceScriptDTO> deviceOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
962 | - deviceOpt.ifPresent(device -> { | ||
963 | - eventPublisher.publishEvent(new ScriptUpdatedEvent(device)); | ||
964 | - }); | ||
965 | - } | ||
966 | - } else if (toSessionMsg.hasEntityDeleteMsg()) { | ||
967 | - TransportProtos.EntityDeleteMsg msg = toSessionMsg.getEntityDeleteMsg(); | ||
968 | - EntityType entityType = EntityType.valueOf(msg.getEntityType()); | ||
969 | - UUID entityUuid = new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB()); | ||
970 | - if (EntityType.DEVICE_PROFILE.equals(entityType)) { | ||
971 | - deviceProfileCache.evict(new DeviceProfileId(new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB()))); | ||
972 | - } else if (EntityType.TENANT_PROFILE.equals(entityType)) { | ||
973 | - tenantProfileCache.remove(new TenantProfileId(entityUuid)); | ||
974 | - } else if (EntityType.TENANT.equals(entityType)) { | ||
975 | - rateLimitService.remove(TenantId.fromUUID(entityUuid)); | ||
976 | - } else if (EntityType.DEVICE.equals(entityType)) { | ||
977 | - rateLimitService.remove(new DeviceId(entityUuid)); | ||
978 | - onDeviceDeleted(new DeviceId(entityUuid)); | ||
979 | - } | ||
980 | - } else if (toSessionMsg.hasResourceUpdateMsg()) { | ||
981 | - TransportProtos.ResourceUpdateMsg msg = toSessionMsg.getResourceUpdateMsg(); | ||
982 | - TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); | ||
983 | - ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); | ||
984 | - String resourceId = msg.getResourceKey(); | ||
985 | - transportResourceCache.update(tenantId, resourceType, resourceId); | ||
986 | - sessions.forEach((id, mdRez) -> { | ||
987 | - log.trace("ResourceUpdate - [{}] [{}]", id, mdRez); | ||
988 | - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(msg)); | ||
989 | - }); | ||
990 | - | ||
991 | - } else if (toSessionMsg.hasResourceDeleteMsg()) { | ||
992 | - TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg(); | ||
993 | - TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); | ||
994 | - ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); | ||
995 | - String resourceId = msg.getResourceKey(); | ||
996 | - transportResourceCache.evict(tenantId, resourceType, resourceId); | ||
997 | - sessions.forEach((id, mdRez) -> { | ||
998 | - log.warn("ResourceDelete - [{}] [{}]", id, mdRez); | ||
999 | - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(msg)); | ||
1000 | - }); | ||
1001 | - } else { | ||
1002 | - //TODO: should we notify the device actor about missed session? | ||
1003 | - log.debug("[{}] Missing session.", sessionId); | 1229 | + if (toSessionMsg.hasToServerResponse()) { |
1230 | + String requestId = | ||
1231 | + sessionId + "-" + toSessionMsg.getToServerResponse().getRequestId(); | ||
1232 | + toServerRpcPendingMap.remove(requestId); | ||
1233 | + listener.onToServerRpcResponse(toSessionMsg.getToServerResponse()); | ||
1234 | + } | ||
1235 | + }); | ||
1236 | + if (md.getSessionType() == TransportProtos.SessionType.SYNC) { | ||
1237 | + deregisterSession(md.getSessionInfo()); | ||
1238 | + } | ||
1239 | + } else { | ||
1240 | + log.trace("Processing broadcast notification: {}", toSessionMsg); | ||
1241 | + if (toSessionMsg.hasEntityUpdateMsg()) { | ||
1242 | + TransportProtos.EntityUpdateMsg msg = toSessionMsg.getEntityUpdateMsg(); | ||
1243 | + EntityType entityType = EntityType.valueOf(msg.getEntityType()); | ||
1244 | + if (EntityType.DEVICE_PROFILE.equals(entityType)) { | ||
1245 | + DeviceProfile deviceProfile = deviceProfileCache.put(msg.getData()); | ||
1246 | + if (deviceProfile != null) { | ||
1247 | + log.info("On device profile update: {}", deviceProfile); | ||
1248 | + onProfileUpdate(deviceProfile); | ||
1249 | + } | ||
1250 | + } else if (EntityType.TENANT_PROFILE.equals(entityType)) { | ||
1251 | + rateLimitService.update(tenantProfileCache.put(msg.getData())); | ||
1252 | + } else if (EntityType.TENANT.equals(entityType)) { | ||
1253 | + Optional<Tenant> profileOpt = | ||
1254 | + dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
1255 | + if (profileOpt.isPresent()) { | ||
1256 | + Tenant tenant = profileOpt.get(); | ||
1257 | + boolean updated = tenantProfileCache.put(tenant.getId(), tenant.getTenantProfileId()); | ||
1258 | + if (updated) { | ||
1259 | + rateLimitService.update(tenant.getId()); | ||
1004 | } | 1260 | } |
1261 | + } | ||
1262 | + } else if (EntityType.API_USAGE_STATE.equals(entityType)) { | ||
1263 | + Optional<ApiUsageState> stateOpt = | ||
1264 | + dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
1265 | + if (stateOpt.isPresent()) { | ||
1266 | + ApiUsageState apiUsageState = stateOpt.get(); | ||
1267 | + rateLimitService.update( | ||
1268 | + apiUsageState.getTenantId(), apiUsageState.isTransportEnabled()); | ||
1269 | + // TODO: if transport is disabled, we should close all sessions and not to check | ||
1270 | + // credentials. | ||
1271 | + } | ||
1272 | + } else if (EntityType.DEVICE.equals(entityType)) { | ||
1273 | + Optional<Device> deviceOpt = | ||
1274 | + dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
1275 | + deviceOpt.ifPresent( | ||
1276 | + device -> { | ||
1277 | + onDeviceUpdate(device); | ||
1278 | + eventPublisher.publishEvent(new DeviceUpdatedEvent(device)); | ||
1279 | + }); | ||
1280 | + | ||
1281 | + // Thingskit function | ||
1282 | + } else if (EntityType.JS_SCRIPT.equals(entityType)) { | ||
1283 | + Optional<TkDeviceScriptDTO> deviceOpt = | ||
1284 | + dataDecodingEncodingService.decode(msg.getData().toByteArray()); | ||
1285 | + deviceOpt.ifPresent( | ||
1286 | + device -> { | ||
1287 | + eventPublisher.publishEvent(new ScriptUpdatedEvent(device)); | ||
1288 | + }); | ||
1005 | } | 1289 | } |
1006 | - } | ||
1007 | - | 1290 | + } else if (toSessionMsg.hasEntityDeleteMsg()) { |
1291 | + TransportProtos.EntityDeleteMsg msg = toSessionMsg.getEntityDeleteMsg(); | ||
1292 | + EntityType entityType = EntityType.valueOf(msg.getEntityType()); | ||
1293 | + UUID entityUuid = new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB()); | ||
1294 | + if (EntityType.DEVICE_PROFILE.equals(entityType)) { | ||
1295 | + deviceProfileCache.evict( | ||
1296 | + new DeviceProfileId(new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB()))); | ||
1297 | + } else if (EntityType.TENANT_PROFILE.equals(entityType)) { | ||
1298 | + tenantProfileCache.remove(new TenantProfileId(entityUuid)); | ||
1299 | + } else if (EntityType.TENANT.equals(entityType)) { | ||
1300 | + rateLimitService.remove(TenantId.fromUUID(entityUuid)); | ||
1301 | + } else if (EntityType.DEVICE.equals(entityType)) { | ||
1302 | + rateLimitService.remove(new DeviceId(entityUuid)); | ||
1303 | + onDeviceDeleted(new DeviceId(entityUuid)); | ||
1304 | + } | ||
1305 | + } else if (toSessionMsg.hasResourceUpdateMsg()) { | ||
1306 | + TransportProtos.ResourceUpdateMsg msg = toSessionMsg.getResourceUpdateMsg(); | ||
1307 | + TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); | ||
1308 | + ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); | ||
1309 | + String resourceId = msg.getResourceKey(); | ||
1310 | + transportResourceCache.update(tenantId, resourceType, resourceId); | ||
1311 | + sessions.forEach( | ||
1312 | + (id, mdRez) -> { | ||
1313 | + log.trace("ResourceUpdate - [{}] [{}]", id, mdRez); | ||
1314 | + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(msg)); | ||
1315 | + }); | ||
1008 | 1316 | ||
1009 | - public void onProfileUpdate(DeviceProfile deviceProfile) { | ||
1010 | - long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits(); | ||
1011 | - long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits(); | ||
1012 | - sessions.forEach((id, md) -> { | ||
1013 | - //TODO: if transport types are different - we should close the session. | ||
1014 | - if (md.getSessionInfo().getDeviceProfileIdMSB() == deviceProfileIdMSB | ||
1015 | - && md.getSessionInfo().getDeviceProfileIdLSB() == deviceProfileIdLSB) { | ||
1016 | - TransportProtos.SessionInfoProto newSessionInfo = TransportProtos.SessionInfoProto.newBuilder() | ||
1017 | - .mergeFrom(md.getSessionInfo()) | ||
1018 | - .setDeviceProfileIdMSB(deviceProfileIdMSB) | ||
1019 | - .setDeviceProfileIdLSB(deviceProfileIdLSB) | ||
1020 | - .setDeviceType(deviceProfile.getName()) | ||
1021 | - .build(); | ||
1022 | - md.setSessionInfo(newSessionInfo); | ||
1023 | - transportCallbackExecutor.submit(() -> md.getListener().onDeviceProfileUpdate(newSessionInfo, deviceProfile)); | ||
1024 | - } | 1317 | + } else if (toSessionMsg.hasResourceDeleteMsg()) { |
1318 | + TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg(); | ||
1319 | + TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB())); | ||
1320 | + ResourceType resourceType = ResourceType.valueOf(msg.getResourceType()); | ||
1321 | + String resourceId = msg.getResourceKey(); | ||
1322 | + transportResourceCache.evict(tenantId, resourceType, resourceId); | ||
1323 | + sessions.forEach( | ||
1324 | + (id, mdRez) -> { | ||
1325 | + log.warn("ResourceDelete - [{}] [{}]", id, mdRez); | ||
1326 | + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(msg)); | ||
1327 | + }); | ||
1328 | + } else { | ||
1329 | + // TODO: should we notify the device actor about missed session? | ||
1330 | + log.debug("[{}] Missing session.", sessionId); | ||
1331 | + } | ||
1332 | + } | ||
1333 | + } | ||
1334 | + | ||
1335 | + public void onProfileUpdate(DeviceProfile deviceProfile) { | ||
1336 | + long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits(); | ||
1337 | + long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits(); | ||
1338 | + sessions.forEach( | ||
1339 | + (id, md) -> { | ||
1340 | + // TODO: if transport types are different - we should close the session. | ||
1341 | + if (md.getSessionInfo().getDeviceProfileIdMSB() == deviceProfileIdMSB | ||
1342 | + && md.getSessionInfo().getDeviceProfileIdLSB() == deviceProfileIdLSB) { | ||
1343 | + TransportProtos.SessionInfoProto newSessionInfo = | ||
1344 | + TransportProtos.SessionInfoProto.newBuilder() | ||
1345 | + .mergeFrom(md.getSessionInfo()) | ||
1346 | + .setDeviceProfileIdMSB(deviceProfileIdMSB) | ||
1347 | + .setDeviceProfileIdLSB(deviceProfileIdLSB) | ||
1348 | + .setDeviceType(deviceProfile.getName()) | ||
1349 | + .build(); | ||
1350 | + md.setSessionInfo(newSessionInfo); | ||
1351 | + transportCallbackExecutor.submit( | ||
1352 | + () -> md.getListener().onDeviceProfileUpdate(newSessionInfo, deviceProfile)); | ||
1353 | + } | ||
1025 | }); | 1354 | }); |
1026 | - } | ||
1027 | - | ||
1028 | - private void onDeviceUpdate(Device device) { | ||
1029 | - long deviceIdMSB = device.getId().getId().getMostSignificantBits(); | ||
1030 | - long deviceIdLSB = device.getId().getId().getLeastSignificantBits(); | ||
1031 | - long deviceProfileIdMSB = device.getDeviceProfileId().getId().getMostSignificantBits(); | ||
1032 | - long deviceProfileIdLSB = device.getDeviceProfileId().getId().getLeastSignificantBits(); | ||
1033 | - sessions.forEach((id, md) -> { | ||
1034 | - if ((md.getSessionInfo().getDeviceIdMSB() == deviceIdMSB && md.getSessionInfo().getDeviceIdLSB() == deviceIdLSB)) { | ||
1035 | - DeviceProfile newDeviceProfile; | ||
1036 | - if (md.getSessionInfo().getDeviceProfileIdMSB() != deviceProfileIdMSB | ||
1037 | - || md.getSessionInfo().getDeviceProfileIdLSB() != deviceProfileIdLSB) { | ||
1038 | - //TODO: if transport types are different - we should close the session. | ||
1039 | - newDeviceProfile = deviceProfileCache.get(new DeviceProfileId(new UUID(deviceProfileIdMSB, deviceProfileIdLSB))); | ||
1040 | - } else { | ||
1041 | - newDeviceProfile = null; | ||
1042 | - } | ||
1043 | - TransportProtos.SessionInfoProto newSessionInfo = TransportProtos.SessionInfoProto.newBuilder() | ||
1044 | - .mergeFrom(md.getSessionInfo()) | ||
1045 | - .setDeviceProfileIdMSB(deviceProfileIdMSB) | ||
1046 | - .setDeviceProfileIdLSB(deviceProfileIdLSB) | ||
1047 | - .setDeviceName(device.getName()) | ||
1048 | - .setDeviceType(device.getType()).build(); | ||
1049 | - if (device.getAdditionalInfo().has("gateway") | ||
1050 | - && device.getAdditionalInfo().get("gateway").asBoolean() | ||
1051 | - && device.getAdditionalInfo().has(OVERWRITE_ACTIVITY_TIME) | ||
1052 | - && device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).isBoolean()) { | ||
1053 | - md.setOverwriteActivityTime(device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).asBoolean()); | ||
1054 | - } | ||
1055 | - md.setSessionInfo(newSessionInfo); | ||
1056 | - transportCallbackExecutor.submit(() -> md.getListener().onDeviceUpdate(newSessionInfo, device, Optional.ofNullable(newDeviceProfile))); | 1355 | + } |
1356 | + | ||
1357 | + private void onDeviceUpdate(Device device) { | ||
1358 | + long deviceIdMSB = device.getId().getId().getMostSignificantBits(); | ||
1359 | + long deviceIdLSB = device.getId().getId().getLeastSignificantBits(); | ||
1360 | + long deviceProfileIdMSB = device.getDeviceProfileId().getId().getMostSignificantBits(); | ||
1361 | + long deviceProfileIdLSB = device.getDeviceProfileId().getId().getLeastSignificantBits(); | ||
1362 | + sessions.forEach( | ||
1363 | + (id, md) -> { | ||
1364 | + if ((md.getSessionInfo().getDeviceIdMSB() == deviceIdMSB | ||
1365 | + && md.getSessionInfo().getDeviceIdLSB() == deviceIdLSB)) { | ||
1366 | + DeviceProfile newDeviceProfile; | ||
1367 | + if (md.getSessionInfo().getDeviceProfileIdMSB() != deviceProfileIdMSB | ||
1368 | + || md.getSessionInfo().getDeviceProfileIdLSB() != deviceProfileIdLSB) { | ||
1369 | + // TODO: if transport types are different - we should close the session. | ||
1370 | + newDeviceProfile = | ||
1371 | + deviceProfileCache.get( | ||
1372 | + new DeviceProfileId(new UUID(deviceProfileIdMSB, deviceProfileIdLSB))); | ||
1373 | + } else { | ||
1374 | + newDeviceProfile = null; | ||
1375 | + } | ||
1376 | + TransportProtos.SessionInfoProto newSessionInfo = | ||
1377 | + TransportProtos.SessionInfoProto.newBuilder() | ||
1378 | + .mergeFrom(md.getSessionInfo()) | ||
1379 | + .setDeviceProfileIdMSB(deviceProfileIdMSB) | ||
1380 | + .setDeviceProfileIdLSB(deviceProfileIdLSB) | ||
1381 | + .setDeviceName(device.getName()) | ||
1382 | + .setDeviceType(device.getType()) | ||
1383 | + .build(); | ||
1384 | + if (device.getAdditionalInfo().has("gateway") | ||
1385 | + && device.getAdditionalInfo().get("gateway").asBoolean() | ||
1386 | + && device.getAdditionalInfo().has(OVERWRITE_ACTIVITY_TIME) | ||
1387 | + && device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).isBoolean()) { | ||
1388 | + md.setOverwriteActivityTime( | ||
1389 | + device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).asBoolean()); | ||
1057 | } | 1390 | } |
1391 | + md.setSessionInfo(newSessionInfo); | ||
1392 | + transportCallbackExecutor.submit( | ||
1393 | + () -> | ||
1394 | + md.getListener() | ||
1395 | + .onDeviceUpdate( | ||
1396 | + newSessionInfo, device, Optional.ofNullable(newDeviceProfile))); | ||
1397 | + } | ||
1058 | }); | 1398 | }); |
1059 | - } | ||
1060 | - | ||
1061 | - private void onDeviceDeleted(DeviceId deviceId) { | ||
1062 | - sessions.forEach((id, md) -> { | ||
1063 | - DeviceId sessionDeviceId = new DeviceId(new UUID(md.getSessionInfo().getDeviceIdMSB(), md.getSessionInfo().getDeviceIdLSB())); | ||
1064 | - if (sessionDeviceId.equals(deviceId)) { | ||
1065 | - transportCallbackExecutor.submit(() -> { | ||
1066 | - md.getListener().onDeviceDeleted(deviceId); | 1399 | + } |
1400 | + | ||
1401 | + private void onDeviceDeleted(DeviceId deviceId) { | ||
1402 | + sessions.forEach( | ||
1403 | + (id, md) -> { | ||
1404 | + DeviceId sessionDeviceId = | ||
1405 | + new DeviceId( | ||
1406 | + new UUID( | ||
1407 | + md.getSessionInfo().getDeviceIdMSB(), md.getSessionInfo().getDeviceIdLSB())); | ||
1408 | + if (sessionDeviceId.equals(deviceId)) { | ||
1409 | + transportCallbackExecutor.submit( | ||
1410 | + () -> { | ||
1411 | + md.getListener().onDeviceDeleted(deviceId); | ||
1067 | }); | 1412 | }); |
1068 | - } | 1413 | + } |
1069 | }); | 1414 | }); |
1415 | + } | ||
1416 | + | ||
1417 | + protected UUID toSessionId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1418 | + return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | ||
1419 | + } | ||
1420 | + | ||
1421 | + protected UUID getRoutingKey(TransportProtos.SessionInfoProto sessionInfo) { | ||
1422 | + return new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()); | ||
1423 | + } | ||
1424 | + | ||
1425 | + protected TenantId getTenantId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1426 | + return TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB())); | ||
1427 | + } | ||
1428 | + | ||
1429 | + protected CustomerId getCustomerId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1430 | + long msb = sessionInfo.getCustomerIdMSB(); | ||
1431 | + long lsb = sessionInfo.getCustomerIdLSB(); | ||
1432 | + if (msb != 0 && lsb != 0) { | ||
1433 | + return new CustomerId(new UUID(msb, lsb)); | ||
1434 | + } else { | ||
1435 | + return new CustomerId(EntityId.NULL_UUID); | ||
1436 | + } | ||
1437 | + } | ||
1438 | + | ||
1439 | + protected DeviceId getDeviceId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1440 | + return new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
1441 | + } | ||
1442 | + | ||
1443 | + private static TransportProtos.SessionEventMsg getSessionEventMsg( | ||
1444 | + TransportProtos.SessionEvent event) { | ||
1445 | + return TransportProtos.SessionEventMsg.newBuilder() | ||
1446 | + .setSessionType(TransportProtos.SessionType.ASYNC) | ||
1447 | + .setEvent(event) | ||
1448 | + .build(); | ||
1449 | + } | ||
1450 | + | ||
1451 | + protected void sendToDeviceActor( | ||
1452 | + TransportProtos.SessionInfoProto sessionInfo, | ||
1453 | + TransportToDeviceActorMsg toDeviceActorMsg, | ||
1454 | + TransportServiceCallback<Void> callback) { | ||
1455 | + TopicPartitionInfo tpi = | ||
1456 | + partitionService.resolve( | ||
1457 | + ServiceType.TB_CORE, getTenantId(sessionInfo), getDeviceId(sessionInfo)); | ||
1458 | + if (log.isTraceEnabled()) { | ||
1459 | + log.trace( | ||
1460 | + "[{}][{}] Pushing to topic {} message {}", | ||
1461 | + getTenantId(sessionInfo), | ||
1462 | + getDeviceId(sessionInfo), | ||
1463 | + tpi.getFullTopicName(), | ||
1464 | + toDeviceActorMsg); | ||
1465 | + } | ||
1466 | + TransportTbQueueCallback transportTbQueueCallback = | ||
1467 | + callback != null ? new TransportTbQueueCallback(callback) : null; | ||
1468 | + tbCoreProducerStats.incrementTotal(); | ||
1469 | + StatsCallback wrappedCallback = | ||
1470 | + new StatsCallback(transportTbQueueCallback, tbCoreProducerStats); | ||
1471 | + tbCoreMsgProducer.send( | ||
1472 | + tpi, | ||
1473 | + new TbProtoQueueMsg<>( | ||
1474 | + getRoutingKey(sessionInfo), | ||
1475 | + ToCoreMsg.newBuilder().setToDeviceActorMsg(toDeviceActorMsg).build()), | ||
1476 | + wrappedCallback); | ||
1477 | + } | ||
1478 | + | ||
1479 | + private void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) { | ||
1480 | + TopicPartitionInfo tpi = | ||
1481 | + partitionService.resolve( | ||
1482 | + ServiceType.TB_RULE_ENGINE, tbMsg.getQueueName(), tenantId, tbMsg.getOriginator()); | ||
1483 | + if (log.isTraceEnabled()) { | ||
1484 | + log.trace( | ||
1485 | + "[{}][{}] Pushing to topic {} message {}", | ||
1486 | + tenantId, | ||
1487 | + tbMsg.getOriginator(), | ||
1488 | + tpi.getFullTopicName(), | ||
1489 | + tbMsg); | ||
1490 | + } | ||
1491 | + ToRuleEngineMsg msg = | ||
1492 | + ToRuleEngineMsg.newBuilder() | ||
1493 | + .setTbMsg(TbMsg.toByteString(tbMsg)) | ||
1494 | + .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) | ||
1495 | + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) | ||
1496 | + .build(); | ||
1497 | + ruleEngineProducerStats.incrementTotal(); | ||
1498 | + StatsCallback wrappedCallback = new StatsCallback(callback, ruleEngineProducerStats); | ||
1499 | + ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), wrappedCallback); | ||
1500 | + } | ||
1501 | + | ||
1502 | + private void sendToRuleEngine( | ||
1503 | + TenantId tenantId, | ||
1504 | + DeviceId deviceId, | ||
1505 | + CustomerId customerId, | ||
1506 | + TransportProtos.SessionInfoProto sessionInfo, | ||
1507 | + JsonObject json, | ||
1508 | + TbMsgMetaData metaData, | ||
1509 | + SessionMsgType sessionMsgType, | ||
1510 | + TbQueueCallback callback) { | ||
1511 | + DeviceProfileId deviceProfileId = | ||
1512 | + new DeviceProfileId( | ||
1513 | + new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | ||
1514 | + DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId); | ||
1515 | + RuleChainId ruleChainId; | ||
1516 | + String queueName; | ||
1517 | + | ||
1518 | + if (deviceProfile == null) { | ||
1519 | + log.warn("[{}] Device profile is null!", deviceProfileId); | ||
1520 | + ruleChainId = null; | ||
1521 | + queueName = ServiceQueue.MAIN; | ||
1522 | + } else { | ||
1523 | + ruleChainId = deviceProfile.getDefaultRuleChainId(); | ||
1524 | + String defaultQueueName = deviceProfile.getDefaultQueueName(); | ||
1525 | + queueName = defaultQueueName != null ? defaultQueueName : ServiceQueue.MAIN; | ||
1526 | + } | ||
1527 | + | ||
1528 | + TbMsg tbMsg = | ||
1529 | + TbMsg.newMsg( | ||
1530 | + queueName, | ||
1531 | + sessionMsgType.name(), | ||
1532 | + deviceId, | ||
1533 | + customerId, | ||
1534 | + metaData, | ||
1535 | + gson.toJson(json), | ||
1536 | + ruleChainId, | ||
1537 | + null); | ||
1538 | + sendToRuleEngine(tenantId, tbMsg, callback); | ||
1539 | + } | ||
1540 | + | ||
1541 | + private class TransportTbQueueCallback implements TbQueueCallback { | ||
1542 | + private final TransportServiceCallback<Void> callback; | ||
1543 | + | ||
1544 | + private TransportTbQueueCallback(TransportServiceCallback<Void> callback) { | ||
1545 | + this.callback = callback; | ||
1070 | } | 1546 | } |
1071 | 1547 | ||
1072 | - protected UUID toSessionId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1073 | - return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()); | ||
1074 | - } | ||
1075 | - | ||
1076 | - protected UUID getRoutingKey(TransportProtos.SessionInfoProto sessionInfo) { | ||
1077 | - return new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()); | ||
1078 | - } | ||
1079 | - | ||
1080 | - protected TenantId getTenantId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1081 | - return TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB())); | ||
1082 | - } | ||
1083 | - | ||
1084 | - protected CustomerId getCustomerId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1085 | - long msb = sessionInfo.getCustomerIdMSB(); | ||
1086 | - long lsb = sessionInfo.getCustomerIdLSB(); | ||
1087 | - if (msb != 0 && lsb != 0) { | ||
1088 | - return new CustomerId(new UUID(msb, lsb)); | ||
1089 | - } else { | ||
1090 | - return new CustomerId(EntityId.NULL_UUID); | ||
1091 | - } | ||
1092 | - } | ||
1093 | - | ||
1094 | - protected DeviceId getDeviceId(TransportProtos.SessionInfoProto sessionInfo) { | ||
1095 | - return new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); | ||
1096 | - } | ||
1097 | - | ||
1098 | - private static TransportProtos.SessionEventMsg getSessionEventMsg(TransportProtos.SessionEvent event) { | ||
1099 | - return TransportProtos.SessionEventMsg.newBuilder() | ||
1100 | - .setSessionType(TransportProtos.SessionType.ASYNC) | ||
1101 | - .setEvent(event).build(); | ||
1102 | - } | ||
1103 | - | ||
1104 | - protected void sendToDeviceActor(TransportProtos.SessionInfoProto sessionInfo, TransportToDeviceActorMsg toDeviceActorMsg, TransportServiceCallback<Void> callback) { | ||
1105 | - TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, getTenantId(sessionInfo), getDeviceId(sessionInfo)); | ||
1106 | - if (log.isTraceEnabled()) { | ||
1107 | - log.trace("[{}][{}] Pushing to topic {} message {}", getTenantId(sessionInfo), getDeviceId(sessionInfo), tpi.getFullTopicName(), toDeviceActorMsg); | ||
1108 | - } | ||
1109 | - TransportTbQueueCallback transportTbQueueCallback = callback != null ? | ||
1110 | - new TransportTbQueueCallback(callback) : null; | ||
1111 | - tbCoreProducerStats.incrementTotal(); | ||
1112 | - StatsCallback wrappedCallback = new StatsCallback(transportTbQueueCallback, tbCoreProducerStats); | ||
1113 | - tbCoreMsgProducer.send(tpi, | ||
1114 | - new TbProtoQueueMsg<>(getRoutingKey(sessionInfo), | ||
1115 | - ToCoreMsg.newBuilder().setToDeviceActorMsg(toDeviceActorMsg).build()), | ||
1116 | - wrappedCallback); | 1548 | + @Override |
1549 | + public void onSuccess(TbQueueMsgMetadata metadata) { | ||
1550 | + DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onSuccess(null)); | ||
1117 | } | 1551 | } |
1118 | 1552 | ||
1119 | - private void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) { | ||
1120 | - TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_RULE_ENGINE, tbMsg.getQueueName(), tenantId, tbMsg.getOriginator()); | ||
1121 | - if (log.isTraceEnabled()) { | ||
1122 | - log.trace("[{}][{}] Pushing to topic {} message {}", tenantId, tbMsg.getOriginator(), tpi.getFullTopicName(), tbMsg); | ||
1123 | - } | ||
1124 | - ToRuleEngineMsg msg = ToRuleEngineMsg.newBuilder().setTbMsg(TbMsg.toByteString(tbMsg)) | ||
1125 | - .setTenantIdMSB(tenantId.getId().getMostSignificantBits()) | ||
1126 | - .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()).build(); | ||
1127 | - ruleEngineProducerStats.incrementTotal(); | ||
1128 | - StatsCallback wrappedCallback = new StatsCallback(callback, ruleEngineProducerStats); | ||
1129 | - ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), wrappedCallback); | 1553 | + @Override |
1554 | + public void onFailure(Throwable t) { | ||
1555 | + DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t)); | ||
1130 | } | 1556 | } |
1557 | + } | ||
1131 | 1558 | ||
1132 | - private void sendToRuleEngine(TenantId tenantId, DeviceId deviceId, CustomerId customerId, TransportProtos.SessionInfoProto sessionInfo, JsonObject json, | ||
1133 | - TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) { | ||
1134 | - DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | ||
1135 | - DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId); | ||
1136 | - RuleChainId ruleChainId; | ||
1137 | - String queueName; | ||
1138 | - | ||
1139 | - if (deviceProfile == null) { | ||
1140 | - log.warn("[{}] Device profile is null!", deviceProfileId); | ||
1141 | - ruleChainId = null; | ||
1142 | - queueName = ServiceQueue.MAIN; | ||
1143 | - } else { | ||
1144 | - ruleChainId = deviceProfile.getDefaultRuleChainId(); | ||
1145 | - String defaultQueueName = deviceProfile.getDefaultQueueName(); | ||
1146 | - queueName = defaultQueueName != null ? defaultQueueName : ServiceQueue.MAIN; | ||
1147 | - } | 1559 | + private static class StatsCallback implements TbQueueCallback { |
1560 | + private final TbQueueCallback callback; | ||
1561 | + private final MessagesStats stats; | ||
1148 | 1562 | ||
1149 | - TbMsg tbMsg = TbMsg.newMsg(queueName, sessionMsgType.name(), deviceId, customerId, metaData, gson.toJson(json), ruleChainId, null); | ||
1150 | - sendToRuleEngine(tenantId, tbMsg, callback); | 1563 | + private StatsCallback(TbQueueCallback callback, MessagesStats stats) { |
1564 | + this.callback = callback; | ||
1565 | + this.stats = stats; | ||
1151 | } | 1566 | } |
1152 | 1567 | ||
1153 | - private class TransportTbQueueCallback implements TbQueueCallback { | ||
1154 | - private final TransportServiceCallback<Void> callback; | ||
1155 | - | ||
1156 | - private TransportTbQueueCallback(TransportServiceCallback<Void> callback) { | ||
1157 | - this.callback = callback; | ||
1158 | - } | ||
1159 | - | ||
1160 | - @Override | ||
1161 | - public void onSuccess(TbQueueMsgMetadata metadata) { | ||
1162 | - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onSuccess(null)); | ||
1163 | - } | ||
1164 | - | ||
1165 | - @Override | ||
1166 | - public void onFailure(Throwable t) { | ||
1167 | - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t)); | ||
1168 | - } | 1568 | + @Override |
1569 | + public void onSuccess(TbQueueMsgMetadata metadata) { | ||
1570 | + stats.incrementSuccessful(); | ||
1571 | + if (callback != null) callback.onSuccess(metadata); | ||
1169 | } | 1572 | } |
1170 | 1573 | ||
1171 | - private static class StatsCallback implements TbQueueCallback { | ||
1172 | - private final TbQueueCallback callback; | ||
1173 | - private final MessagesStats stats; | ||
1174 | - | ||
1175 | - private StatsCallback(TbQueueCallback callback, MessagesStats stats) { | ||
1176 | - this.callback = callback; | ||
1177 | - this.stats = stats; | ||
1178 | - } | ||
1179 | - | ||
1180 | - @Override | ||
1181 | - public void onSuccess(TbQueueMsgMetadata metadata) { | ||
1182 | - stats.incrementSuccessful(); | ||
1183 | - if (callback != null) | ||
1184 | - callback.onSuccess(metadata); | ||
1185 | - } | ||
1186 | - | ||
1187 | - @Override | ||
1188 | - public void onFailure(Throwable t) { | ||
1189 | - stats.incrementFailed(); | ||
1190 | - if (callback != null) | ||
1191 | - callback.onFailure(t); | ||
1192 | - } | 1574 | + @Override |
1575 | + public void onFailure(Throwable t) { | ||
1576 | + stats.incrementFailed(); | ||
1577 | + if (callback != null) callback.onFailure(t); | ||
1193 | } | 1578 | } |
1579 | + } | ||
1194 | 1580 | ||
1195 | - private class MsgPackCallback implements TbQueueCallback { | ||
1196 | - private final AtomicInteger msgCount; | ||
1197 | - private final TransportServiceCallback<Void> callback; | 1581 | + private class MsgPackCallback implements TbQueueCallback { |
1582 | + private final AtomicInteger msgCount; | ||
1583 | + private final TransportServiceCallback<Void> callback; | ||
1198 | 1584 | ||
1199 | - public MsgPackCallback(Integer msgCount, TransportServiceCallback<Void> callback) { | ||
1200 | - this.msgCount = new AtomicInteger(msgCount); | ||
1201 | - this.callback = callback; | ||
1202 | - } | ||
1203 | - | ||
1204 | - @Override | ||
1205 | - public void onSuccess(TbQueueMsgMetadata metadata) { | ||
1206 | - if (msgCount.decrementAndGet() <= 0) { | ||
1207 | - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onSuccess(null)); | ||
1208 | - } | ||
1209 | - } | ||
1210 | - | ||
1211 | - @Override | ||
1212 | - public void onFailure(Throwable t) { | ||
1213 | - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t)); | ||
1214 | - } | ||
1215 | - } | ||
1216 | - | ||
1217 | - private class ApiStatsProxyCallback<T> implements TransportServiceCallback<T> { | ||
1218 | - private final TenantId tenantId; | ||
1219 | - private final CustomerId customerId; | ||
1220 | - private final int dataPoints; | ||
1221 | - private final TransportServiceCallback<T> callback; | ||
1222 | - | ||
1223 | - public ApiStatsProxyCallback(TenantId tenantId, CustomerId customerId, int dataPoints, TransportServiceCallback<T> callback) { | ||
1224 | - this.tenantId = tenantId; | ||
1225 | - this.customerId = customerId; | ||
1226 | - this.dataPoints = dataPoints; | ||
1227 | - this.callback = callback; | ||
1228 | - } | ||
1229 | - | ||
1230 | - @Override | ||
1231 | - public void onSuccess(T msg) { | ||
1232 | - try { | ||
1233 | - apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.TRANSPORT_MSG_COUNT, 1); | ||
1234 | - apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.TRANSPORT_DP_COUNT, dataPoints); | ||
1235 | - } finally { | ||
1236 | - callback.onSuccess(msg); | ||
1237 | - } | ||
1238 | - } | ||
1239 | - | ||
1240 | - @Override | ||
1241 | - public void onError(Throwable e) { | ||
1242 | - callback.onError(e); | ||
1243 | - } | 1585 | + public MsgPackCallback(Integer msgCount, TransportServiceCallback<Void> callback) { |
1586 | + this.msgCount = new AtomicInteger(msgCount); | ||
1587 | + this.callback = callback; | ||
1244 | } | 1588 | } |
1245 | 1589 | ||
1246 | @Override | 1590 | @Override |
1247 | - public ExecutorService getCallbackExecutor() { | ||
1248 | - return transportCallbackExecutor; | 1591 | + public void onSuccess(TbQueueMsgMetadata metadata) { |
1592 | + if (msgCount.decrementAndGet() <= 0) { | ||
1593 | + DefaultTransportService.this.transportCallbackExecutor.submit( | ||
1594 | + () -> callback.onSuccess(null)); | ||
1595 | + } | ||
1249 | } | 1596 | } |
1250 | 1597 | ||
1251 | @Override | 1598 | @Override |
1252 | - public boolean hasSession(TransportProtos.SessionInfoProto sessionInfo) { | ||
1253 | - return sessions.containsKey(toSessionId(sessionInfo)); | 1599 | + public void onFailure(Throwable t) { |
1600 | + DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t)); | ||
1254 | } | 1601 | } |
1602 | + } | ||
1255 | 1603 | ||
1256 | - @Override | ||
1257 | - public void createGaugeStats(String statsName, AtomicInteger number) { | ||
1258 | - statsFactory.createGauge(StatsType.TRANSPORT + "." + statsName, number); | ||
1259 | - statsMap.put(statsName, number); | ||
1260 | - } | 1604 | + private class ApiStatsProxyCallback<T> implements TransportServiceCallback<T> { |
1605 | + private final TenantId tenantId; | ||
1606 | + private final CustomerId customerId; | ||
1607 | + private final int dataPoints; | ||
1608 | + private final TransportServiceCallback<T> callback; | ||
1261 | 1609 | ||
1262 | - @Scheduled(fixedDelayString = "${transport.stats.print-interval-ms:60000}") | ||
1263 | - public void printStats() { | ||
1264 | - if (statsEnabled && !statsMap.isEmpty()) { | ||
1265 | - String values = statsMap.entrySet().stream() | ||
1266 | - .map(kv -> kv.getKey() + " [" + kv.getValue() + "]").collect(Collectors.joining(", ")); | ||
1267 | - log.info("Transport Stats: {}", values); | ||
1268 | - } | 1610 | + public ApiStatsProxyCallback( |
1611 | + TenantId tenantId, | ||
1612 | + CustomerId customerId, | ||
1613 | + int dataPoints, | ||
1614 | + TransportServiceCallback<T> callback) { | ||
1615 | + this.tenantId = tenantId; | ||
1616 | + this.customerId = customerId; | ||
1617 | + this.dataPoints = dataPoints; | ||
1618 | + this.callback = callback; | ||
1269 | } | 1619 | } |
1270 | 1620 | ||
1271 | - | ||
1272 | - | ||
1273 | - | ||
1274 | - | ||
1275 | - | ||
1276 | - | ||
1277 | - | ||
1278 | - | ||
1279 | - //Thingskit function | ||
1280 | @Override | 1621 | @Override |
1281 | - public List<ScriptProto> getScripts(ScriptProto msg) { | ||
1282 | - TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg = | ||
1283 | - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setScript(msg).build()); | ||
1284 | - try { | ||
1285 | - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get(); | ||
1286 | - return response.getValue().getScriptsResponseMsgList(); | ||
1287 | - } catch (InterruptedException | ExecutionException e) { | ||
1288 | - throw new RuntimeException(e); | ||
1289 | - } | 1622 | + public void onSuccess(T msg) { |
1623 | + try { | ||
1624 | + apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.TRANSPORT_MSG_COUNT, 1); | ||
1625 | + apiUsageClient.report( | ||
1626 | + tenantId, customerId, ApiUsageRecordKey.TRANSPORT_DP_COUNT, dataPoints); | ||
1627 | + } finally { | ||
1628 | + callback.onSuccess(msg); | ||
1629 | + } | ||
1290 | } | 1630 | } |
1291 | 1631 | ||
1292 | - //thingskit | ||
1293 | @Override | 1632 | @Override |
1294 | - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.Gbt28181RequestMsg msg, | ||
1295 | - TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback) { | ||
1296 | - if (checkLimits(sessionInfo, msg, callback)) { | ||
1297 | - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
1298 | - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setGbt28181RequestMsg(msg).build()); | ||
1299 | - | ||
1300 | - AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), response -> { | ||
1301 | - callback.onSuccess(response.getValue().getGbt28181ResponseMsg()); | ||
1302 | - }, callback::onError, transportCallbackExecutor); | ||
1303 | - } | ||
1304 | - } | 1633 | + public void onError(Throwable e) { |
1634 | + callback.onError(e); | ||
1635 | + } | ||
1636 | + } | ||
1637 | + | ||
1638 | + @Override | ||
1639 | + public ExecutorService getCallbackExecutor() { | ||
1640 | + return transportCallbackExecutor; | ||
1641 | + } | ||
1642 | + | ||
1643 | + @Override | ||
1644 | + public boolean hasSession(TransportProtos.SessionInfoProto sessionInfo) { | ||
1645 | + return sessions.containsKey(toSessionId(sessionInfo)); | ||
1646 | + } | ||
1647 | + | ||
1648 | + @Override | ||
1649 | + public void createGaugeStats(String statsName, AtomicInteger number) { | ||
1650 | + statsFactory.createGauge(StatsType.TRANSPORT + "." + statsName, number); | ||
1651 | + statsMap.put(statsName, number); | ||
1652 | + } | ||
1653 | + | ||
1654 | + @Scheduled(fixedDelayString = "${transport.stats.print-interval-ms:60000}") | ||
1655 | + public void printStats() { | ||
1656 | + if (statsEnabled && !statsMap.isEmpty()) { | ||
1657 | + String values = | ||
1658 | + statsMap.entrySet().stream() | ||
1659 | + .map(kv -> kv.getKey() + " [" + kv.getValue() + "]") | ||
1660 | + .collect(Collectors.joining(", ")); | ||
1661 | + log.info("Transport Stats: {}", values); | ||
1662 | + } | ||
1663 | + } | ||
1664 | + | ||
1665 | + // Thingskit function | ||
1666 | + @Override | ||
1667 | + public List<ScriptProto> getScripts(ScriptProto msg) { | ||
1668 | + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg = | ||
1669 | + new TbProtoQueueMsg<>( | ||
1670 | + UUID.randomUUID(), | ||
1671 | + TransportProtos.TransportApiRequestMsg.newBuilder().setScript(msg).build()); | ||
1672 | + try { | ||
1673 | + TbProtoQueueMsg<TransportApiResponseMsg> response = | ||
1674 | + transportApiRequestTemplate.send(protoMsg).get(); | ||
1675 | + return response.getValue().getScriptsResponseMsgList(); | ||
1676 | + } catch (InterruptedException | ExecutionException e) { | ||
1677 | + throw new RuntimeException(e); | ||
1678 | + } | ||
1679 | + } | ||
1680 | + | ||
1681 | + // thingskit | ||
1682 | + @Override | ||
1683 | + public void process( | ||
1684 | + TransportProtos.SessionInfoProto sessionInfo, | ||
1685 | + TransportProtos.Gbt28181RequestMsg msg, | ||
1686 | + TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback) { | ||
1687 | + if (checkLimits(sessionInfo, msg, callback)) { | ||
1688 | + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = | ||
1689 | + new TbProtoQueueMsg<>( | ||
1690 | + UUID.randomUUID(), | ||
1691 | + TransportApiRequestMsg.newBuilder().setGbt28181RequestMsg(msg).build()); | ||
1692 | + | ||
1693 | + AsyncCallbackTemplate.withCallback( | ||
1694 | + transportApiRequestTemplate.send(protoMsg), | ||
1695 | + response -> { | ||
1696 | + callback.onSuccess(response.getValue().getGbt28181ResponseMsg()); | ||
1697 | + }, | ||
1698 | + callback::onError, | ||
1699 | + transportCallbackExecutor); | ||
1700 | + } | ||
1701 | + } | ||
1702 | + | ||
1703 | + @Override | ||
1704 | + public List<TransportProtos.Gbt28181MediaServerMsg> freshGtb28181Media( | ||
1705 | + TransportProtos.Gbt28181MediaServerMsg msg) { | ||
1706 | + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg = | ||
1707 | + new TbProtoQueueMsg<>( | ||
1708 | + UUID.randomUUID(), | ||
1709 | + TransportProtos.TransportApiRequestMsg.newBuilder() | ||
1710 | + .setGbt28181MediaServerMsg(msg) | ||
1711 | + .build()); | ||
1712 | + try { | ||
1713 | + TbProtoQueueMsg<TransportApiResponseMsg> response = | ||
1714 | + transportApiRequestTemplate.send(protoMsg).get(); | ||
1715 | + return response.getValue().getGbt28181MediaServerMsgList(); | ||
1716 | + } catch (InterruptedException | ExecutionException e) { | ||
1717 | + throw new RuntimeException(e); | ||
1718 | + } | ||
1719 | + } | ||
1305 | } | 1720 | } |
@@ -4,7 +4,6 @@ import java.util.*; | @@ -4,7 +4,6 @@ import java.util.*; | ||
4 | import lombok.extern.slf4j.Slf4j; | 4 | import lombok.extern.slf4j.Slf4j; |
5 | import org.springframework.beans.factory.annotation.Autowired; | 5 | import org.springframework.beans.factory.annotation.Autowired; |
6 | import org.springframework.stereotype.Component; | 6 | import org.springframework.stereotype.Component; |
7 | -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig; | ||
8 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | 7 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
9 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 8 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
10 | import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | 9 | import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; |
@@ -16,7 +15,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio | @@ -16,7 +15,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio | ||
16 | public class SSRCFactory { | 15 | public class SSRCFactory { |
17 | 16 | ||
18 | /** 播流最大并发个数 */ | 17 | /** 播流最大并发个数 */ |
19 | - private static final Integer MAX_STREAM_COUNT = 10000; | 18 | + private static final Integer MAX_STREAM_COUNT = 300; |
20 | 19 | ||
21 | /** 播流最大并发个数 */ | 20 | /** 播流最大并发个数 */ |
22 | private static final String SSRC_INFO_KEY = "TK_SSRC_INFO_"; | 21 | private static final String SSRC_INFO_KEY = "TK_SSRC_INFO_"; |
@@ -24,26 +23,29 @@ public class SSRCFactory { | @@ -24,26 +23,29 @@ public class SSRCFactory { | ||
24 | private final String cacheName = FastIotConstants.MediaServerKey.MEDIA_SERVER_CACHE_NAME; | 23 | private final String cacheName = FastIotConstants.MediaServerKey.MEDIA_SERVER_CACHE_NAME; |
25 | @Autowired private CacheUtils cacheUtils; | 24 | @Autowired private CacheUtils cacheUtils; |
26 | 25 | ||
27 | - @Autowired private SipConfig sipConfig; | ||
28 | - | ||
29 | @Autowired private UserSetting userSetting; | 26 | @Autowired private UserSetting userSetting; |
30 | 27 | ||
31 | public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) { | 28 | public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) { |
32 | - String ssrcPrefix = sipConfig.getDomain().substring(3, 8); | ||
33 | - String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId; | ||
34 | - Set<String> ssrcList = new HashSet<>(); | ||
35 | - for (int i = 1; i < MAX_STREAM_COUNT; i++) { | ||
36 | - String ssrc = String.format("%s%04d", ssrcPrefix, i); | 29 | + Optional<String> sipDomain = |
30 | + cacheUtils.get(FastIotConstants.CacheSipKey.TK_SIP_CACHE_NAME, mediaServerId); | ||
31 | + sipDomain.ifPresent( | ||
32 | + domain -> { | ||
33 | + String ssrcPrefix = domain.substring(3, 8); | ||
34 | + String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId; | ||
35 | + Set<String> ssrcList = new HashSet<>(); | ||
36 | + for (int i = 1; i < MAX_STREAM_COUNT; i++) { | ||
37 | + String ssrc = String.format("%s%04d", ssrcPrefix, i); | ||
37 | 38 | ||
38 | - if (null == usedSet || !usedSet.contains(ssrc)) { | ||
39 | - ssrcList.add(ssrc); | ||
40 | - } | ||
41 | - } | ||
42 | - if (cacheUtils.get(cacheName, redisKey).isPresent()) { | ||
43 | - cacheUtils.invalidate(cacheName, redisKey); | ||
44 | - } | ||
45 | - // 把这10000个ssrc放入缓存 | ||
46 | - cacheUtils.put(cacheName, redisKey, ssrcList); | 39 | + if (null == usedSet || !usedSet.contains(ssrc)) { |
40 | + ssrcList.add(ssrc); | ||
41 | + } | ||
42 | + } | ||
43 | + if (cacheUtils.get(cacheName, redisKey).isPresent()) { | ||
44 | + cacheUtils.invalidate(cacheName, redisKey); | ||
45 | + } | ||
46 | + // 把这10000个ssrc放入缓存 | ||
47 | + cacheUtils.put(cacheName, redisKey, ssrcList); | ||
48 | + }); | ||
47 | } | 49 | } |
48 | 50 | ||
49 | /** | 51 | /** |
@@ -3,15 +3,13 @@ package org.thingsboard.server.dao.yunteng.factory; | @@ -3,15 +3,13 @@ package org.thingsboard.server.dao.yunteng.factory; | ||
3 | import java.text.ParseException; | 3 | import java.text.ParseException; |
4 | import java.util.*; | 4 | import java.util.*; |
5 | import java.util.concurrent.ConcurrentHashMap; | 5 | import java.util.concurrent.ConcurrentHashMap; |
6 | - | ||
7 | import lombok.RequiredArgsConstructor; | 6 | import lombok.RequiredArgsConstructor; |
8 | import lombok.extern.slf4j.Slf4j; | 7 | import lombok.extern.slf4j.Slf4j; |
9 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
9 | +import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | ||
10 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; | 10 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; |
11 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.ChannelOnlineEvent; | 11 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.ChannelOnlineEvent; |
12 | -import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.OnStreamChangedHookParam; | ||
13 | import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; | 12 | import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; |
14 | -import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | ||
15 | import org.thingsboard.server.dao.yunteng.service.media.TkCacheStorageService; | 13 | import org.thingsboard.server.dao.yunteng.service.media.TkCacheStorageService; |
16 | 14 | ||
17 | @Component | 15 | @Component |
@@ -24,31 +22,36 @@ public class ZLMMediaListManager { | @@ -24,31 +22,36 @@ public class ZLMMediaListManager { | ||
24 | private final ZLMRTPServerFactory zlmrtpServerFactory; | 22 | private final ZLMRTPServerFactory zlmrtpServerFactory; |
25 | private final TkCacheStorageService tkCacheStorageService; | 23 | private final TkCacheStorageService tkCacheStorageService; |
26 | private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>(); | 24 | private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>(); |
27 | -// public StreamPushItem addPush(OnStreamChangedHookParam onStreamChangedHookParam) { | ||
28 | -// StreamPushItem transform = streamPushService.transform(onStreamChangedHookParam); | ||
29 | -// StreamPushItem pushInDb = streamPushService.getPush(onStreamChangedHookParam.getApp(), onStreamChangedHookParam.getStream()); | ||
30 | -// transform.setPushIng(onStreamChangedHookParam.isRegist()); | ||
31 | -// transform.setUpdateTime(DateUtil.getNow()); | ||
32 | -// transform.setPushTime(DateUtil.getNow()); | ||
33 | -// transform.setSelf(userSetting.getServerId().equals(onStreamChangedHookParam.getSeverId())); | ||
34 | -// if (pushInDb == null) { | ||
35 | -// transform.setCreateTime(DateUtil.getNow()); | ||
36 | -// streamPushMapper.add(transform); | ||
37 | -// }else { | ||
38 | -// streamPushMapper.update(transform); | ||
39 | -// gbStreamMapper.updateMediaServer(onStreamChangedHookParam.getApp(), onStreamChangedHookParam.getStream(), onStreamChangedHookParam.getMediaServerId()); | ||
40 | -// } | ||
41 | -// ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream()); | ||
42 | -// if ( channelOnlineEventLister != null) { | ||
43 | -// try { | ||
44 | -// channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());; | ||
45 | -// } catch (ParseException e) { | ||
46 | -// logger.error("addPush: ", e); | ||
47 | -// } | ||
48 | -// removedChannelOnlineEventLister(transform.getApp(), transform.getStream()); | ||
49 | -// } | ||
50 | -// return transform; | ||
51 | -// } | 25 | + |
26 | + // public StreamPushItem addPush(OnStreamChangedHookParam onStreamChangedHookParam) { | ||
27 | + // StreamPushItem transform = streamPushService.transform(onStreamChangedHookParam); | ||
28 | + // StreamPushItem pushInDb = streamPushService.getPush(onStreamChangedHookParam.getApp(), | ||
29 | + // onStreamChangedHookParam.getStream()); | ||
30 | + // transform.setPushIng(onStreamChangedHookParam.isRegist()); | ||
31 | + // transform.setUpdateTime(DateUtil.getNow()); | ||
32 | + // transform.setPushTime(DateUtil.getNow()); | ||
33 | + // transform.setSelf(userSetting.getServerId().equals(onStreamChangedHookParam.getSeverId())); | ||
34 | + // if (pushInDb == null) { | ||
35 | + // transform.setCreateTime(DateUtil.getNow()); | ||
36 | + // streamPushMapper.add(transform); | ||
37 | + // }else { | ||
38 | + // streamPushMapper.update(transform); | ||
39 | + // gbStreamMapper.updateMediaServer(onStreamChangedHookParam.getApp(), | ||
40 | + // onStreamChangedHookParam.getStream(), onStreamChangedHookParam.getMediaServerId()); | ||
41 | + // } | ||
42 | + // ChannelOnlineEvent channelOnlineEventLister = | ||
43 | + // getChannelOnlineEventLister(transform.getApp(), transform.getStream()); | ||
44 | + // if ( channelOnlineEventLister != null) { | ||
45 | + // try { | ||
46 | + // channelOnlineEventLister.run(transform.getApp(), transform.getStream(), | ||
47 | + // transform.getServerId());; | ||
48 | + // } catch (ParseException e) { | ||
49 | + // logger.error("addPush: ", e); | ||
50 | + // } | ||
51 | + // removedChannelOnlineEventLister(transform.getApp(), transform.getStream()); | ||
52 | + // } | ||
53 | + // return transform; | ||
54 | + // } | ||
52 | public void sendStreamEvent(String app, String stream, String mediaServerId) { | 55 | public void sendStreamEvent(String app, String stream, String mediaServerId) { |
53 | MediaServerDTO mediaServerItem = tkCacheStorageService.findInfoByMediaServerId(mediaServerId); | 56 | MediaServerDTO mediaServerItem = tkCacheStorageService.findInfoByMediaServerId(mediaServerId); |
54 | // 查看推流状态 | 57 | // 查看推流状态 |
@@ -75,7 +75,8 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | @@ -75,7 +75,8 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | ||
75 | } | 75 | } |
76 | 76 | ||
77 | @Override | 77 | @Override |
78 | - public void closeRTPServer(MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback) { | 78 | + public void closeRTPServer( |
79 | + MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback) { | ||
79 | if (mediaServerItem == null) { | 80 | if (mediaServerItem == null) { |
80 | callback.run(false); | 81 | callback.run(false); |
81 | return; | 82 | return; |
@@ -85,13 +86,13 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | @@ -85,13 +86,13 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | ||
85 | 86 | ||
86 | @Override | 87 | @Override |
87 | public void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig) { | 88 | public void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig) { |
89 | + String serverId = zlmServerConfig.getGeneralMediaServerId(); | ||
88 | MediaServerDTO serverItem = | 90 | MediaServerDTO serverItem = |
89 | - tkMediaServerService.findMediaServerInfoById( | ||
90 | - zlmServerConfig.getTenantId(), zlmServerConfig.getGeneralMediaServerId()); | 91 | + tkMediaServerService.findMediaServerInfoById(zlmServerConfig.getTenantId(), serverId); |
91 | if (serverItem == null) { | 92 | if (serverItem == null) { |
92 | log.warn( | 93 | log.warn( |
93 | "[未注册的zlm] 拒接接入:{}来自{}:{}", | 94 | "[未注册的zlm] 拒接接入:{}来自{}:{}", |
94 | - zlmServerConfig.getGeneralMediaServerId(), | 95 | + serverId, |
95 | zlmServerConfig.getIp(), | 96 | zlmServerConfig.getIp(), |
96 | zlmServerConfig.getHttpPort()); | 97 | zlmServerConfig.getHttpPort()); |
97 | log.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致"); | 98 | log.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致"); |
@@ -99,7 +100,7 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | @@ -99,7 +100,7 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | ||
99 | } else { | 100 | } else { |
100 | log.info( | 101 | log.info( |
101 | "[ZLM] 正在连接 : {} -> {}:{}", | 102 | "[ZLM] 正在连接 : {} -> {}:{}", |
102 | - zlmServerConfig.getGeneralMediaServerId(), | 103 | + serverId, |
103 | zlmServerConfig.getIp(), | 104 | zlmServerConfig.getIp(), |
104 | zlmServerConfig.getHttpPort()); | 105 | zlmServerConfig.getHttpPort()); |
105 | } | 106 | } |
@@ -134,14 +135,14 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | @@ -134,14 +135,14 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | ||
134 | zlmServerConfig.getHttpPort()); | 135 | zlmServerConfig.getHttpPort()); |
135 | return; | 136 | return; |
136 | } | 137 | } |
137 | - tkMediaServerService.saveOrUpdateMediaServer(serverItem); | 138 | + tkMediaServerService.updateMediaServer(serverItem); |
138 | String key = | 139 | String key = |
139 | FastIotConstants.MediaServerKey.MEDIA_SERVER_PREFIX | 140 | FastIotConstants.MediaServerKey.MEDIA_SERVER_PREFIX |
140 | + userSetting.getServerId() | 141 | + userSetting.getServerId() |
141 | + "_" | 142 | + "_" |
142 | - + zlmServerConfig.getGeneralMediaServerId(); | 143 | + + serverId; |
143 | if (ssrcFactory.hasMediaServerSSRC(serverItem.getMediaServerId())) { | 144 | if (ssrcFactory.hasMediaServerSSRC(serverItem.getMediaServerId())) { |
144 | - ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); | 145 | + ssrcFactory.initMediaServerSSRC(serverId, null); |
145 | } | 146 | } |
146 | cacheUtils.put(cacheName, key, serverItem); | 147 | cacheUtils.put(cacheName, key, serverItem); |
147 | resetOnlineServerItem(serverItem); | 148 | resetOnlineServerItem(serverItem); |
@@ -161,12 +162,19 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | @@ -161,12 +162,19 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { | ||
161 | } | 162 | } |
162 | 163 | ||
163 | log.info( | 164 | log.info( |
164 | - "[ZLM] 连接成功 {} - {}:{} ", | ||
165 | - zlmServerConfig.getGeneralMediaServerId(), | ||
166 | - zlmServerConfig.getIp(), | ||
167 | - zlmServerConfig.getHttpPort()); | 165 | + "[ZLM] 连接成功 {} - {}:{} ", serverId, zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); |
168 | } | 166 | } |
169 | 167 | ||
168 | + @Override | ||
169 | + public void zlmServerOffline(String medisServerId) { | ||
170 | + MediaServerDTO serverItem = tkMediaServerService.findMediaServerInfoById(null, medisServerId); | ||
171 | + if (serverItem == null) { | ||
172 | + log.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致"); | ||
173 | + return; | ||
174 | + } | ||
175 | + serverItem.setStatus(false); | ||
176 | + tkMediaServerService.updateMediaServer(serverItem); | ||
177 | + } | ||
170 | 178 | ||
171 | @Override | 179 | @Override |
172 | public void resetOnlineServerItem(MediaServerDTO mediaServerItem) { | 180 | public void resetOnlineServerItem(MediaServerDTO mediaServerItem) { |
@@ -24,11 +24,8 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -24,11 +24,8 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
24 | import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; | 24 | import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; |
25 | import org.thingsboard.server.common.data.yunteng.common.media.ZlmHttpHookSubscribe; | 25 | import org.thingsboard.server.common.data.yunteng.common.media.ZlmHttpHookSubscribe; |
26 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | 26 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
27 | -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | ||
28 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 27 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
29 | import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | 28 | import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; |
30 | -import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; | ||
31 | -import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | ||
32 | import org.thingsboard.server.common.data.yunteng.dto.sip.*; | 29 | import org.thingsboard.server.common.data.yunteng.dto.sip.*; |
33 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherPsSendInfo; | 30 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherPsSendInfo; |
34 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherRtpSendInfo; | 31 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherRtpSendInfo; |
@@ -111,7 +108,7 @@ public class TkMediaServerServiceImpl | @@ -111,7 +108,7 @@ public class TkMediaServerServiceImpl | ||
111 | TkMediaServerEntity entity = | 108 | TkMediaServerEntity entity = |
112 | baseMapper.selectOne( | 109 | baseMapper.selectOne( |
113 | new LambdaQueryWrapper<TkMediaServerEntity>() | 110 | new LambdaQueryWrapper<TkMediaServerEntity>() |
114 | - .eq(TkMediaServerEntity::getTenantId, tenantId) | 111 | + // .eq(TkMediaServerEntity::getTenantId, tenantId) |
115 | .eq(TkMediaServerEntity::getMediaServerId, id)); | 112 | .eq(TkMediaServerEntity::getMediaServerId, id)); |
116 | return Optional.ofNullable(entity).map(obj -> obj.getDTO(MediaServerDTO.class)).orElse(null); | 113 | return Optional.ofNullable(entity).map(obj -> obj.getDTO(MediaServerDTO.class)).orElse(null); |
117 | } | 114 | } |
@@ -126,28 +123,24 @@ public class TkMediaServerServiceImpl | @@ -126,28 +123,24 @@ public class TkMediaServerServiceImpl | ||
126 | } | 123 | } |
127 | 124 | ||
128 | @Override | 125 | @Override |
129 | - public MediaServerDTO saveOrUpdateMediaServer(MediaServerDTO mediaServer) { | 126 | + public MediaServerDTO saveMediaServer(MediaServerDTO mediaServer) { |
130 | TkMediaServerEntity entity = mediaServer.getEntity(TkMediaServerEntity.class); | 127 | TkMediaServerEntity entity = mediaServer.getEntity(TkMediaServerEntity.class); |
131 | - if (StringUtils.isEmpty(mediaServer.getId())) { | ||
132 | - baseMapper.insert(entity); | ||
133 | - } else { | ||
134 | - TkMediaServerEntity queryEntity = | ||
135 | - baseMapper.selectOne( | ||
136 | - new LambdaQueryWrapper<TkMediaServerEntity>() | ||
137 | - .eq(TkMediaServerEntity::getTenantId, mediaServer.getTenantId()) | ||
138 | - .eq(TkMediaServerEntity::getId, mediaServer.getId())); | ||
139 | - if (null == queryEntity) { | ||
140 | - throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | ||
141 | - } | ||
142 | - baseMapper.updateById(entity); | ||
143 | - } | ||
144 | - return mediaServer; | 128 | + baseMapper.insert(entity); |
129 | + return entity.getDTO(MediaServerDTO.class); | ||
145 | } | 130 | } |
146 | 131 | ||
147 | @Override | 132 | @Override |
148 | - public MediaServerDTO getMediaServerForMinimumLoad(String tenantId) { | 133 | + public MediaServerDTO updateMediaServer(MediaServerDTO mediaServer) { |
134 | + TkMediaServerEntity entity = mediaServer.getEntity(TkMediaServerEntity.class); | ||
135 | + | ||
136 | + baseMapper.updateById(entity); | ||
137 | + return entity.getDTO(MediaServerDTO.class); | ||
138 | + } | ||
139 | + | ||
140 | + @Override | ||
141 | + public MediaServerDTO getMediaServerForMinimumLoad(String sipId) { | ||
149 | // 先从缓存获取 | 142 | // 先从缓存获取 |
150 | - MediaServerDTO mediaServerDTO = tkCacheStorageService.findMediaServerForMinimumLoad(tenantId); | 143 | + MediaServerDTO mediaServerDTO = tkCacheStorageService.findMediaServerForMinimumLoad(sipId); |
151 | if (null != mediaServerDTO) { | 144 | if (null != mediaServerDTO) { |
152 | return mediaServerDTO; | 145 | return mediaServerDTO; |
153 | } else { | 146 | } else { |
@@ -157,9 +150,9 @@ public class TkMediaServerServiceImpl | @@ -157,9 +150,9 @@ public class TkMediaServerServiceImpl | ||
157 | } | 150 | } |
158 | 151 | ||
159 | @Override | 152 | @Override |
160 | - public MediaServerDTO getMediaServerForPlay(String tenantId, String mediaServerId) { | 153 | + public MediaServerDTO getMediaServerForPlay(String sipId, String mediaServerId) { |
161 | if (StringUtils.isEmpty(mediaServerId)) { | 154 | if (StringUtils.isEmpty(mediaServerId)) { |
162 | - return getMediaServerForMinimumLoad(tenantId); | 155 | + return getMediaServerForMinimumLoad(sipId); |
163 | } else { | 156 | } else { |
164 | return getMediaServerByMediaServerId(mediaServerId); | 157 | return getMediaServerByMediaServerId(mediaServerId); |
165 | } | 158 | } |
@@ -595,7 +588,8 @@ public class TkMediaServerServiceImpl | @@ -595,7 +588,8 @@ public class TkMediaServerServiceImpl | ||
595 | ret.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, playStream.getChannelId()); | 588 | ret.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, playStream.getChannelId()); |
596 | ret.put(FastIotConstants.ZLMediaBody.CAMERA_CODE, playStream.getCameraCode()); | 589 | ret.put(FastIotConstants.ZLMediaBody.CAMERA_CODE, playStream.getCameraCode()); |
597 | ret.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM, playStream.getStream()); | 590 | ret.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM, playStream.getStream()); |
598 | - tkCacheStorageService.deleteCacheStreamInfoByStopPlay(playStream); //redisCatchStorage.stopPlay(streamInfo); | 591 | + tkCacheStorageService.deleteCacheStreamInfoByStopPlay( |
592 | + playStream); // redisCatchStorage.stopPlay(streamInfo); | ||
599 | }); | 593 | }); |
600 | // 点播 | 594 | // 点播 |
601 | // 录像回放 | 595 | // 录像回放 |
@@ -649,8 +643,9 @@ public class TkMediaServerServiceImpl | @@ -649,8 +643,9 @@ public class TkMediaServerServiceImpl | ||
649 | 643 | ||
650 | @Override | 644 | @Override |
651 | public HookResult zlmOnServerKeepalive(OnServerKeepaliveHookParam param) { | 645 | public HookResult zlmOnServerKeepalive(OnServerKeepaliveHookParam param) { |
652 | - executorResponseAllSubscribeByHookTypeEnum( | ||
653 | - HookTypeEnum.ON_SERVER_KEEPALIVE, JacksonUtil.convertValue(param, JsonNode.class), null); | 646 | + // executorResponseAllSubscribeByHookTypeEnum( |
647 | + // HookTypeEnum.ON_SERVER_KEEPALIVE, JacksonUtil.convertValue(param, JsonNode.class), | ||
648 | + // null); | ||
654 | // TODO | 649 | // TODO |
655 | return HookResult.SUCCESS(); | 650 | return HookResult.SUCCESS(); |
656 | } | 651 | } |
@@ -760,22 +755,22 @@ public class TkMediaServerServiceImpl | @@ -760,22 +755,22 @@ public class TkMediaServerServiceImpl | ||
760 | return map; | 755 | return map; |
761 | } | 756 | } |
762 | 757 | ||
763 | - private void executorResponseAllSubscribeByHookTypeEnum( | ||
764 | - HookTypeEnum HookTypeEnum, JsonNode jsonNode, ZLMediaKitServerConfig zlmServerConfig) { | ||
765 | - // taskExecutor.execute( | ||
766 | - // () -> { | ||
767 | - // List<ZlmHttpHookSubscribe.Event> subscribes = | ||
768 | - // this.subscribe.getSubscribes(HookTypeEnum); | ||
769 | - // if (subscribes != null && subscribes.size() > 0) { | ||
770 | - // for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | ||
771 | - // subscribe.response(null, jsonNode); | ||
772 | - // } | ||
773 | - // } | ||
774 | - // if (null != zlmServerConfig) { | ||
775 | - // zlmServerOnline(zlmServerConfig); | ||
776 | - // } | ||
777 | - // }); | ||
778 | - } | 758 | + // private void executorResponseAllSubscribeByHookTypeEnum( |
759 | + // HookTypeEnum HookTypeEnum, JsonNode jsonNode, ZLMediaKitServerConfig zlmServerConfig) { | ||
760 | + // taskExecutor.execute( | ||
761 | + // () -> { | ||
762 | + // List<ZlmHttpHookSubscribe.Event> subscribes = | ||
763 | + // this.subscribe.getSubscribes(HookTypeEnum); | ||
764 | + // if (subscribes != null && subscribes.size() > 0) { | ||
765 | + // for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { | ||
766 | + // subscribe.response(null, jsonNode); | ||
767 | + // } | ||
768 | + // } | ||
769 | + // if (null != zlmServerConfig) { | ||
770 | + // zlmServerOnline(zlmServerConfig); | ||
771 | + // } | ||
772 | + // }); | ||
773 | + // } | ||
779 | 774 | ||
780 | private HookResultForOnPublish appIsNotRtp(BaseParam param, MediaServerDTO mediaInfo) { | 775 | private HookResultForOnPublish appIsNotRtp(BaseParam param, MediaServerDTO mediaInfo) { |
781 | // HookResultForOnPublish hookResultForOnPublish = new HookResultForOnPublish(401, | 776 | // HookResultForOnPublish hookResultForOnPublish = new HookResultForOnPublish(401, |
@@ -60,6 +60,7 @@ public interface TkCacheStorageService { | @@ -60,6 +60,7 @@ public interface TkCacheStorageService { | ||
60 | * @param tenantId 租户ID | 60 | * @param tenantId 租户ID |
61 | * @return 流媒体信息 | 61 | * @return 流媒体信息 |
62 | */ | 62 | */ |
63 | + @Deprecated | ||
63 | MediaServerDTO findMediaServerForMinimumLoad(String tenantId); | 64 | MediaServerDTO findMediaServerForMinimumLoad(String tenantId); |
64 | 65 | ||
65 | /** | 66 | /** |
1 | package org.thingsboard.server.dao.yunteng.service.media; | 1 | package org.thingsboard.server.dao.yunteng.service.media; |
2 | 2 | ||
3 | import java.util.Optional; | 3 | import java.util.Optional; |
4 | - | ||
5 | import org.thingsboard.server.common.data.yunteng.common.media.CommonCallback; | 4 | import org.thingsboard.server.common.data.yunteng.common.media.CommonCallback; |
6 | import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | 5 | import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; |
7 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; | 6 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; |
@@ -20,10 +19,23 @@ public interface TkMediaServerNodeService { | @@ -20,10 +19,23 @@ public interface TkMediaServerNodeService { | ||
20 | /** zlm 重启后重置他的推流信息 */ | 19 | /** zlm 重启后重置他的推流信息 */ |
21 | void clearRTPServer(MediaServerDTO mediaServerItem); | 20 | void clearRTPServer(MediaServerDTO mediaServerItem); |
22 | 21 | ||
23 | - void closeRTPServer(MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback); | 22 | + void closeRTPServer( |
23 | + MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback); | ||
24 | 24 | ||
25 | + /** | ||
26 | + * 处理zlm上线 | ||
27 | + * | ||
28 | + * @param zlmServerConfig ZLM返回的流媒体配置 | ||
29 | + */ | ||
25 | void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig); | 30 | void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig); |
26 | 31 | ||
32 | + /** | ||
33 | + * 处理zlm上线 | ||
34 | + * | ||
35 | + * @param mediaServerId ZLM返回的流媒体配置 | ||
36 | + */ | ||
37 | + void zlmServerOffline(String mediaServerId); | ||
38 | + | ||
27 | void resetOnlineServerItem(MediaServerDTO mediaServerItem); | 39 | void resetOnlineServerItem(MediaServerDTO mediaServerItem); |
28 | 40 | ||
29 | /** | 41 | /** |
1 | package org.thingsboard.server.dao.yunteng.service.media; | 1 | package org.thingsboard.server.dao.yunteng.service.media; |
2 | 2 | ||
3 | import com.fasterxml.jackson.databind.JsonNode; | 3 | import com.fasterxml.jackson.databind.JsonNode; |
4 | +import java.util.List; | ||
4 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; | 5 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; |
5 | import org.thingsboard.server.common.data.yunteng.dto.sip.StreamInfoDTO; | 6 | import org.thingsboard.server.common.data.yunteng.dto.sip.StreamInfoDTO; |
6 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; | 7 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; |
7 | 8 | ||
8 | -import java.util.List; | ||
9 | - | ||
10 | public interface TkMediaServerService { | 9 | public interface TkMediaServerService { |
11 | 10 | ||
12 | /** | 11 | /** |
@@ -15,6 +14,7 @@ public interface TkMediaServerService { | @@ -15,6 +14,7 @@ public interface TkMediaServerService { | ||
15 | * @return 流媒体列表 | 14 | * @return 流媒体列表 |
16 | */ | 15 | */ |
17 | List<MediaServerDTO> getAllMediaKit(); | 16 | List<MediaServerDTO> getAllMediaKit(); |
17 | + | ||
18 | /** | 18 | /** |
19 | * 通过流媒体ID获取流媒体信息 | 19 | * 通过流媒体ID获取流媒体信息 |
20 | * | 20 | * |
@@ -37,7 +37,15 @@ public interface TkMediaServerService { | @@ -37,7 +37,15 @@ public interface TkMediaServerService { | ||
37 | * @param mediaServer 流媒体信息 | 37 | * @param mediaServer 流媒体信息 |
38 | * @return 流媒体信息 | 38 | * @return 流媒体信息 |
39 | */ | 39 | */ |
40 | - MediaServerDTO saveOrUpdateMediaServer(MediaServerDTO mediaServer); | 40 | + MediaServerDTO saveMediaServer(MediaServerDTO mediaServer); |
41 | + | ||
42 | + /** | ||
43 | + * 刷新流媒体信息 | ||
44 | + * | ||
45 | + * @param mediaServer 流媒体信息 | ||
46 | + * @return 流媒体信息 | ||
47 | + */ | ||
48 | + MediaServerDTO updateMediaServer(MediaServerDTO mediaServer); | ||
41 | 49 | ||
42 | /** | 50 | /** |
43 | * 获取当前租户最小负载的流媒体 | 51 | * 获取当前租户最小负载的流媒体 |
@@ -45,6 +53,7 @@ public interface TkMediaServerService { | @@ -45,6 +53,7 @@ public interface TkMediaServerService { | ||
45 | * @param tenantId 租户ID | 53 | * @param tenantId 租户ID |
46 | * @return 流媒体信息 | 54 | * @return 流媒体信息 |
47 | */ | 55 | */ |
56 | + @Deprecated | ||
48 | MediaServerDTO getMediaServerForMinimumLoad(String tenantId); | 57 | MediaServerDTO getMediaServerForMinimumLoad(String tenantId); |
49 | 58 | ||
50 | /** | 59 | /** |
msa/transport/gbt28181/docker/Dockerfile
0 → 100644
1 | +# | ||
2 | +# Copyright © 2016-2022 The Thingsboard Authors | ||
3 | +# | ||
4 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +# you may not use this file except in compliance with the License. | ||
6 | +# You may obtain a copy of the License at | ||
7 | +# | ||
8 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +# | ||
10 | +# Unless required by applicable law or agreed to in writing, software | ||
11 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +# See the License for the specific language governing permissions and | ||
14 | +# limitations under the License. | ||
15 | +# | ||
16 | + | ||
17 | +FROM thingsboard/openjdk11 | ||
18 | + | ||
19 | +COPY start-tb-gbt28181-transport.sh ${pkg.name}.deb /tmp/ | ||
20 | + | ||
21 | +RUN chmod a+x /tmp/*.sh \ | ||
22 | + && mv /tmp/start-tb-gbt28181-transport.sh /usr/bin | ||
23 | + | ||
24 | +RUN yes | dpkg -i /tmp/${pkg.name}.deb | ||
25 | +RUN rm /tmp/${pkg.name}.deb | ||
26 | + | ||
27 | +RUN systemctl --no-reload disable --now ${pkg.name}.service > /dev/null 2>&1 || : | ||
28 | + | ||
29 | +RUN chmod 555 ${pkg.installFolder}/bin/${pkg.name}.jar | ||
30 | + | ||
31 | +USER ${pkg.user} | ||
32 | + | ||
33 | +CMD ["start-tb-gbt28181-transport.sh"] |
1 | +#!/bin/bash | ||
2 | +# | ||
3 | +# Copyright © 2016-2022 The Thingsboard Authors | ||
4 | +# | ||
5 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | +# you may not use this file except in compliance with the License. | ||
7 | +# You may obtain a copy of the License at | ||
8 | +# | ||
9 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +# | ||
11 | +# Unless required by applicable law or agreed to in writing, software | ||
12 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +# See the License for the specific language governing permissions and | ||
15 | +# limitations under the License. | ||
16 | +# | ||
17 | + | ||
18 | +CONF_FOLDER="/config" | ||
19 | +jarfile=${pkg.installFolder}/bin/${pkg.name}.jar | ||
20 | +configfile=${pkg.name}.conf | ||
21 | + | ||
22 | +source "${CONF_FOLDER}/${configfile}" | ||
23 | + | ||
24 | +export LOADER_PATH=/config,${LOADER_PATH} | ||
25 | + | ||
26 | +echo "Starting '${project.name}' ..." | ||
27 | + | ||
28 | +cd ${pkg.installFolder}/bin | ||
29 | + | ||
30 | +exec java -cp ${jarfile} $JAVA_OPTS -Dorg.thingsboard.server.gbt28181.ThingsboardGBT28181TransportApplication \ | ||
31 | + -Dspring.jpa.hibernate.ddl-auto=none \ | ||
32 | + -Dlogging.config=/config/logback.xml \ | ||
33 | + org.springframework.boot.loader.PropertiesLauncher |
msa/transport/gbt28181/pom.xml
0 → 100644
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2022 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + <parent> | ||
22 | + <groupId>org.thingsboard.msa</groupId> | ||
23 | + <version>3.3.4-SNAPSHOT</version> | ||
24 | + <artifactId>transport</artifactId> | ||
25 | + </parent> | ||
26 | + <groupId>org.thingsboard.msa.transport</groupId> | ||
27 | + <artifactId>gbt28181</artifactId> | ||
28 | + <packaging>pom</packaging> | ||
29 | + | ||
30 | + <name>ThingsBoard GBT28181 Transport Microservice</name> | ||
31 | + <url>https://thingsboard.io</url> | ||
32 | + <description>ThingsBoard GBT28181 Transport Microservice</description> | ||
33 | + | ||
34 | + <properties> | ||
35 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
36 | + <main.dir>${basedir}/../../..</main.dir> | ||
37 | + <pkg.name>tb-gbt28181-transport</pkg.name> | ||
38 | + <docker.name>tb-gbt28181-transport</docker.name> | ||
39 | + <pkg.logFolder>/var/log/${pkg.name}</pkg.logFolder> | ||
40 | + <pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder> | ||
41 | + <docker.push-arm-amd-image.phase>pre-integration-test</docker.push-arm-amd-image.phase> | ||
42 | + </properties> | ||
43 | + | ||
44 | + <dependencies> | ||
45 | + <dependency> | ||
46 | + <groupId>org.thingsboard.transport</groupId> | ||
47 | + <artifactId>gbt28181</artifactId> | ||
48 | + <version>${project.version}</version> | ||
49 | + <classifier>deb</classifier> | ||
50 | + <type>deb</type> | ||
51 | + <scope>provided</scope> | ||
52 | + </dependency> | ||
53 | + </dependencies> | ||
54 | + | ||
55 | + <build> | ||
56 | + <plugins> | ||
57 | + <plugin> | ||
58 | + <groupId>org.apache.maven.plugins</groupId> | ||
59 | + <artifactId>maven-dependency-plugin</artifactId> | ||
60 | + <executions> | ||
61 | + <execution> | ||
62 | + <id>copy-tb-gbt28181-transport-deb</id> | ||
63 | + <phase>package</phase> | ||
64 | + <goals> | ||
65 | + <goal>copy</goal> | ||
66 | + </goals> | ||
67 | + <configuration> | ||
68 | + <artifactItems> | ||
69 | + <artifactItem> | ||
70 | + <groupId>org.thingsboard.transport</groupId> | ||
71 | + <artifactId>gbt28181</artifactId> | ||
72 | + <classifier>deb</classifier> | ||
73 | + <type>deb</type> | ||
74 | + <destFileName>${pkg.name}.deb</destFileName> | ||
75 | + <outputDirectory>${project.build.directory}</outputDirectory> | ||
76 | + </artifactItem> | ||
77 | + </artifactItems> | ||
78 | + </configuration> | ||
79 | + </execution> | ||
80 | + </executions> | ||
81 | + </plugin> | ||
82 | + <plugin> | ||
83 | + <groupId>org.apache.maven.plugins</groupId> | ||
84 | + <artifactId>maven-resources-plugin</artifactId> | ||
85 | + <executions> | ||
86 | + <execution> | ||
87 | + <id>copy-docker-config</id> | ||
88 | + <phase>process-resources</phase> | ||
89 | + <goals> | ||
90 | + <goal>copy-resources</goal> | ||
91 | + </goals> | ||
92 | + <configuration> | ||
93 | + <outputDirectory>${project.build.directory}</outputDirectory> | ||
94 | + <resources> | ||
95 | + <resource> | ||
96 | + <directory>docker</directory> | ||
97 | + <filtering>true</filtering> | ||
98 | + </resource> | ||
99 | + </resources> | ||
100 | + </configuration> | ||
101 | + </execution> | ||
102 | + </executions> | ||
103 | + </plugin> | ||
104 | + <plugin> | ||
105 | + <groupId>com.spotify</groupId> | ||
106 | + <artifactId>dockerfile-maven-plugin</artifactId> | ||
107 | + <executions> | ||
108 | + <execution> | ||
109 | + <id>build-docker-image</id> | ||
110 | + <phase>pre-integration-test</phase> | ||
111 | + <goals> | ||
112 | + <goal>build</goal> | ||
113 | + </goals> | ||
114 | + <configuration> | ||
115 | + <skip>${dockerfile.skip}</skip> | ||
116 | + <repository>${docker.repo}/${docker.name}</repository> | ||
117 | + <verbose>true</verbose> | ||
118 | + <googleContainerRegistryEnabled>false</googleContainerRegistryEnabled> | ||
119 | + <contextDirectory>${project.build.directory}</contextDirectory> | ||
120 | + </configuration> | ||
121 | + </execution> | ||
122 | + <execution> | ||
123 | + <id>tag-docker-image</id> | ||
124 | + <phase>pre-integration-test</phase> | ||
125 | + <goals> | ||
126 | + <goal>tag</goal> | ||
127 | + </goals> | ||
128 | + <configuration> | ||
129 | + <skip>${dockerfile.skip}</skip> | ||
130 | + <repository>${docker.repo}/${docker.name}</repository> | ||
131 | + <tag>${project.version}</tag> | ||
132 | + </configuration> | ||
133 | + </execution> | ||
134 | + </executions> | ||
135 | + </plugin> | ||
136 | + </plugins> | ||
137 | + </build> | ||
138 | + <profiles> | ||
139 | + <profile> | ||
140 | + <id>push-docker-image</id> | ||
141 | + <activation> | ||
142 | + <property> | ||
143 | + <name>push-docker-image</name> | ||
144 | + </property> | ||
145 | + </activation> | ||
146 | + <build> | ||
147 | + <plugins> | ||
148 | + <plugin> | ||
149 | + <groupId>com.spotify</groupId> | ||
150 | + <artifactId>dockerfile-maven-plugin</artifactId> | ||
151 | + <executions> | ||
152 | + <execution> | ||
153 | + <id>push-latest-docker-image</id> | ||
154 | + <phase>pre-integration-test</phase> | ||
155 | + <goals> | ||
156 | + <goal>push</goal> | ||
157 | + </goals> | ||
158 | + <configuration> | ||
159 | + <tag>latest</tag> | ||
160 | + <repository>${docker.repo}/${docker.name}</repository> | ||
161 | + </configuration> | ||
162 | + </execution> | ||
163 | + <execution> | ||
164 | + <id>push-version-docker-image</id> | ||
165 | + <phase>pre-integration-test</phase> | ||
166 | + <goals> | ||
167 | + <goal>push</goal> | ||
168 | + </goals> | ||
169 | + <configuration> | ||
170 | + <tag>${project.version}</tag> | ||
171 | + <repository>${docker.repo}/${docker.name}</repository> | ||
172 | + </configuration> | ||
173 | + </execution> | ||
174 | + </executions> | ||
175 | + </plugin> | ||
176 | + </plugins> | ||
177 | + </build> | ||
178 | + </profile> | ||
179 | + </profiles> | ||
180 | + <repositories> | ||
181 | + <repository> | ||
182 | + <id>jenkins</id> | ||
183 | + <name>Jenkins Repository</name> | ||
184 | + <url>https://repo.jenkins-ci.org/releases</url> | ||
185 | + <snapshots> | ||
186 | + <enabled>false</enabled> | ||
187 | + </snapshots> | ||
188 | + </repository> | ||
189 | + </repositories> | ||
190 | +</project> |
@@ -40,5 +40,7 @@ | @@ -40,5 +40,7 @@ | ||
40 | <module>coap</module> | 40 | <module>coap</module> |
41 | <module>lwm2m</module> | 41 | <module>lwm2m</module> |
42 | <module>snmp</module> | 42 | <module>snmp</module> |
43 | + <module>tcp</module> | ||
44 | + <module>gbt28181</module> | ||
43 | </modules> | 45 | </modules> |
44 | </project> | 46 | </project> |
msa/transport/tcp/docker/Dockerfile
0 → 100644
1 | +# | ||
2 | +# Copyright © 2016-2022 The Thingsboard Authors | ||
3 | +# | ||
4 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | +# you may not use this file except in compliance with the License. | ||
6 | +# You may obtain a copy of the License at | ||
7 | +# | ||
8 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | +# | ||
10 | +# Unless required by applicable law or agreed to in writing, software | ||
11 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | +# See the License for the specific language governing permissions and | ||
14 | +# limitations under the License. | ||
15 | +# | ||
16 | + | ||
17 | +FROM thingsboard/openjdk11 | ||
18 | + | ||
19 | +COPY start-tb-tcp-transport.sh ${pkg.name}.deb /tmp/ | ||
20 | + | ||
21 | +RUN chmod a+x /tmp/*.sh \ | ||
22 | + && mv /tmp/start-tb-tcp-transport.sh /usr/bin | ||
23 | + | ||
24 | +RUN yes | dpkg -i /tmp/${pkg.name}.deb | ||
25 | +RUN rm /tmp/${pkg.name}.deb | ||
26 | + | ||
27 | +RUN systemctl --no-reload disable --now ${pkg.name}.service > /dev/null 2>&1 || : | ||
28 | + | ||
29 | +RUN chmod 555 ${pkg.installFolder}/bin/${pkg.name}.jar | ||
30 | + | ||
31 | +USER ${pkg.user} | ||
32 | + | ||
33 | +CMD ["start-tb-tcp-transport.sh"] |
1 | +#!/bin/bash | ||
2 | +# | ||
3 | +# Copyright © 2016-2022 The Thingsboard Authors | ||
4 | +# | ||
5 | +# Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | +# you may not use this file except in compliance with the License. | ||
7 | +# You may obtain a copy of the License at | ||
8 | +# | ||
9 | +# http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | +# | ||
11 | +# Unless required by applicable law or agreed to in writing, software | ||
12 | +# distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | +# See the License for the specific language governing permissions and | ||
15 | +# limitations under the License. | ||
16 | +# | ||
17 | + | ||
18 | +CONF_FOLDER="/config" | ||
19 | +jarfile=${pkg.installFolder}/bin/${pkg.name}.jar | ||
20 | +configfile=${pkg.name}.conf | ||
21 | + | ||
22 | +source "${CONF_FOLDER}/${configfile}" | ||
23 | + | ||
24 | +export LOADER_PATH=/config,${LOADER_PATH} | ||
25 | + | ||
26 | +echo "Starting '${project.name}' ..." | ||
27 | + | ||
28 | +cd ${pkg.installFolder}/bin | ||
29 | + | ||
30 | +exec java -cp ${jarfile} $JAVA_OPTS -Dloader.main=org.thingsboard.server.tcp.ThingsboardTcpTransportApplication \ | ||
31 | + -Dspring.jpa.hibernate.ddl-auto=none \ | ||
32 | + -Dlogging.config=/config/logback.xml \ | ||
33 | + org.springframework.boot.loader.PropertiesLauncher |
msa/transport/tcp/pom.xml
0 → 100644
1 | +<!-- | ||
2 | + | ||
3 | + Copyright © 2016-2022 The Thingsboard Authors | ||
4 | + | ||
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + you may not use this file except in compliance with the License. | ||
7 | + You may obtain a copy of the License at | ||
8 | + | ||
9 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + | ||
11 | + Unless required by applicable law or agreed to in writing, software | ||
12 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + See the License for the specific language governing permissions and | ||
15 | + limitations under the License. | ||
16 | + | ||
17 | +--> | ||
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + <parent> | ||
22 | + <groupId>org.thingsboard.msa</groupId> | ||
23 | + <version>3.3.4-SNAPSHOT</version> | ||
24 | + <artifactId>transport</artifactId> | ||
25 | + </parent> | ||
26 | + <groupId>org.thingsboard.msa.transport</groupId> | ||
27 | + <artifactId>tcp</artifactId> | ||
28 | + <packaging>pom</packaging> | ||
29 | + | ||
30 | + <name>ThingsBoard TCP/UDP Transport Microservice</name> | ||
31 | + <url>https://thingsboard.io</url> | ||
32 | + <description>ThingsBoard TCP/UDP Transport Microservice</description> | ||
33 | + | ||
34 | + <properties> | ||
35 | + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
36 | + <main.dir>${basedir}/../../..</main.dir> | ||
37 | + <pkg.name>tb-tcp-transport</pkg.name> | ||
38 | + <docker.name>tb-tcp-transport</docker.name> | ||
39 | + <pkg.logFolder>/var/log/${pkg.name}</pkg.logFolder> | ||
40 | + <pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder> | ||
41 | + <docker.push-arm-amd-image.phase>pre-integration-test</docker.push-arm-amd-image.phase> | ||
42 | + </properties> | ||
43 | + | ||
44 | + <dependencies> | ||
45 | + <dependency> | ||
46 | + <groupId>org.thingsboard.transport</groupId> | ||
47 | + <artifactId>tcp</artifactId> | ||
48 | + <version>${project.version}</version> | ||
49 | + <classifier>deb</classifier> | ||
50 | + <type>deb</type> | ||
51 | + <scope>provided</scope> | ||
52 | + </dependency> | ||
53 | + </dependencies> | ||
54 | + | ||
55 | + <build> | ||
56 | + <plugins> | ||
57 | + <plugin> | ||
58 | + <groupId>org.apache.maven.plugins</groupId> | ||
59 | + <artifactId>maven-dependency-plugin</artifactId> | ||
60 | + <executions> | ||
61 | + <execution> | ||
62 | + <id>copy-tb-tcp-transport-deb</id> | ||
63 | + <phase>package</phase> | ||
64 | + <goals> | ||
65 | + <goal>copy</goal> | ||
66 | + </goals> | ||
67 | + <configuration> | ||
68 | + <artifactItems> | ||
69 | + <artifactItem> | ||
70 | + <groupId>org.thingsboard.transport</groupId> | ||
71 | + <artifactId>tcp</artifactId> | ||
72 | + <classifier>deb</classifier> | ||
73 | + <type>deb</type> | ||
74 | + <destFileName>${pkg.name}.deb</destFileName> | ||
75 | + <outputDirectory>${project.build.directory}</outputDirectory> | ||
76 | + </artifactItem> | ||
77 | + </artifactItems> | ||
78 | + </configuration> | ||
79 | + </execution> | ||
80 | + </executions> | ||
81 | + </plugin> | ||
82 | + <plugin> | ||
83 | + <groupId>org.apache.maven.plugins</groupId> | ||
84 | + <artifactId>maven-resources-plugin</artifactId> | ||
85 | + <executions> | ||
86 | + <execution> | ||
87 | + <id>copy-docker-config</id> | ||
88 | + <phase>process-resources</phase> | ||
89 | + <goals> | ||
90 | + <goal>copy-resources</goal> | ||
91 | + </goals> | ||
92 | + <configuration> | ||
93 | + <outputDirectory>${project.build.directory}</outputDirectory> | ||
94 | + <resources> | ||
95 | + <resource> | ||
96 | + <directory>docker</directory> | ||
97 | + <filtering>true</filtering> | ||
98 | + </resource> | ||
99 | + </resources> | ||
100 | + </configuration> | ||
101 | + </execution> | ||
102 | + </executions> | ||
103 | + </plugin> | ||
104 | + <plugin> | ||
105 | + <groupId>com.spotify</groupId> | ||
106 | + <artifactId>dockerfile-maven-plugin</artifactId> | ||
107 | + <executions> | ||
108 | + <execution> | ||
109 | + <id>build-docker-image</id> | ||
110 | + <phase>pre-integration-test</phase> | ||
111 | + <goals> | ||
112 | + <goal>build</goal> | ||
113 | + </goals> | ||
114 | + <configuration> | ||
115 | + <skip>${dockerfile.skip}</skip> | ||
116 | + <repository>${docker.repo}/${docker.name}</repository> | ||
117 | + <verbose>true</verbose> | ||
118 | + <googleContainerRegistryEnabled>false</googleContainerRegistryEnabled> | ||
119 | + <contextDirectory>${project.build.directory}</contextDirectory> | ||
120 | + </configuration> | ||
121 | + </execution> | ||
122 | + <execution> | ||
123 | + <id>tag-docker-image</id> | ||
124 | + <phase>pre-integration-test</phase> | ||
125 | + <goals> | ||
126 | + <goal>tag</goal> | ||
127 | + </goals> | ||
128 | + <configuration> | ||
129 | + <skip>${dockerfile.skip}</skip> | ||
130 | + <repository>${docker.repo}/${docker.name}</repository> | ||
131 | + <tag>${project.version}</tag> | ||
132 | + </configuration> | ||
133 | + </execution> | ||
134 | + </executions> | ||
135 | + </plugin> | ||
136 | + </plugins> | ||
137 | + </build> | ||
138 | + <profiles> | ||
139 | + <profile> | ||
140 | + <id>push-docker-image</id> | ||
141 | + <activation> | ||
142 | + <property> | ||
143 | + <name>push-docker-image</name> | ||
144 | + </property> | ||
145 | + </activation> | ||
146 | + <build> | ||
147 | + <plugins> | ||
148 | + <plugin> | ||
149 | + <groupId>com.spotify</groupId> | ||
150 | + <artifactId>dockerfile-maven-plugin</artifactId> | ||
151 | + <executions> | ||
152 | + <execution> | ||
153 | + <id>push-latest-docker-image</id> | ||
154 | + <phase>pre-integration-test</phase> | ||
155 | + <goals> | ||
156 | + <goal>push</goal> | ||
157 | + </goals> | ||
158 | + <configuration> | ||
159 | + <tag>latest</tag> | ||
160 | + <repository>${docker.repo}/${docker.name}</repository> | ||
161 | + </configuration> | ||
162 | + </execution> | ||
163 | + <execution> | ||
164 | + <id>push-version-docker-image</id> | ||
165 | + <phase>pre-integration-test</phase> | ||
166 | + <goals> | ||
167 | + <goal>push</goal> | ||
168 | + </goals> | ||
169 | + <configuration> | ||
170 | + <tag>${project.version}</tag> | ||
171 | + <repository>${docker.repo}/${docker.name}</repository> | ||
172 | + </configuration> | ||
173 | + </execution> | ||
174 | + </executions> | ||
175 | + </plugin> | ||
176 | + </plugins> | ||
177 | + </build> | ||
178 | + </profile> | ||
179 | + </profiles> | ||
180 | + <repositories> | ||
181 | + <repository> | ||
182 | + <id>jenkins</id> | ||
183 | + <name>Jenkins Repository</name> | ||
184 | + <url>https://repo.jenkins-ci.org/releases</url> | ||
185 | + <snapshots> | ||
186 | + <enabled>false</enabled> | ||
187 | + </snapshots> | ||
188 | + </repository> | ||
189 | + </repositories> | ||
190 | +</project> |
@@ -119,58 +119,49 @@ js: | @@ -119,58 +119,49 @@ js: | ||
119 | enabled: "${TB_JS_REMOTE_STATS_ENABLED:false}" | 119 | enabled: "${TB_JS_REMOTE_STATS_ENABLED:false}" |
120 | print_interval_ms: "${TB_JS_REMOTE_STATS_PRINT_INTERVAL_MS:10000}" | 120 | print_interval_ms: "${TB_JS_REMOTE_STATS_PRINT_INTERVAL_MS:10000}" |
121 | 121 | ||
122 | -# GBT28181_ server parameters | 122 | +# GBT28181 server parameters |
123 | transport: | 123 | transport: |
124 | gbt28181: | 124 | gbt28181: |
125 | - bind_address: "${TCP_BIND_ADDRESS:0.0.0.0}" | ||
126 | - bind_port: "${TCP_BIND_PORT:8088}" | ||
127 | - # Enable proxy protocol support. Disabled by default. If enabled, supports both v1 and v2. | ||
128 | - # Useful to get the real IP address of the client in the logs and for rate limits. | ||
129 | - proxy_enabled: "${TCP_PROXY_PROTOCOL_ENABLED:false}" | ||
130 | - timeout: "${TCP_TIMEOUT:10000}" | ||
131 | - msg_queue_size_per_device_limit: "${TCP_MSG_QUEUE_SIZE_PER_DEVICE_LIMIT:100}" # messages await in the queue before device connected state. This limit works on low level before TenantProfileLimits mechanism | ||
132 | - netty: | ||
133 | - leak_detector_level: "${NETTY_LEAK_DETECTOR_LVL:DISABLED}" | ||
134 | - boss_group_thread_count: "${NETTY_BOSS_GROUP_THREADS:1}" | ||
135 | - worker_group_thread_count: "${NETTY_WORKER_GROUP_THREADS:12}" | ||
136 | - max_payload_size: "${NETTY_MAX_PAYLOAD_SIZE:65536}" | ||
137 | - so_keep_alive: "${NETTY_SO_KEEPALIVE:false}" | ||
138 | - # TCP_ SSL configuration | ||
139 | - ssl: | ||
140 | - # Enable/disable SSL support | ||
141 | - enabled: "${TCP_SSL_ENABLED:false}" | ||
142 | - # TCP_ SSL bind address | ||
143 | - bind_address: "${TCP_SSL_BIND_ADDRESS:0.0.0.0}" | ||
144 | - # TCP_ SSL bind port | ||
145 | - bind_port: "${TCP_SSL_BIND_PORT:8883}" | ||
146 | - # SSL protocol: See https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#sslcontext-algorithms | ||
147 | - protocol: "${TCP_SSL_PROTOCOL:TLSv1.2}" | ||
148 | - # Server SSL credentials | ||
149 | - credentials: | ||
150 | - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore) | ||
151 | - type: "${TCP_SSL_CREDENTIALS_TYPE:PEM}" | ||
152 | - # PEM server credentials | ||
153 | - pem: | ||
154 | - # Path to the server certificate file (holds server certificate or certificate chain, may include server private key) | ||
155 | - cert_file: "${TCP_SSL_PEM_CERT:tcpserver.pem}" | ||
156 | - # Path to the server certificate private key file. Optional by default. Required if the private key is not present in server certificate file; | ||
157 | - key_file: "${TCP_SSL_PEM_KEY:tcpserver_key.pem}" | ||
158 | - # Server certificate private key password (optional) | ||
159 | - key_password: "${TCP_SSL_PEM_KEY_PASSWORD:server_key_password}" | ||
160 | - # Keystore server credentials | ||
161 | - keystore: | ||
162 | - # Type of the key store | ||
163 | - type: "${TCP_SSL_KEY_STORE_TYPE:JKS}" | ||
164 | - # Path to the key store that holds the SSL certificate | ||
165 | - store_file: "${TCP_SSL_KEY_STORE:tcpserver.jks}" | ||
166 | - # Password used to access the key store | ||
167 | - store_password: "${TCP_SSL_KEY_STORE_PASSWORD:server_ks_password}" | ||
168 | - # Optional alias of the private key; If not set, the platform will load the first private key from the keystore; | ||
169 | - key_alias: "${TCP_SSL_KEY_ALIAS:}" | ||
170 | - # Password used to access the key | ||
171 | - key_password: "${TCP_SSL_KEY_PASSWORD:server_key_password}" | ||
172 | - # Skip certificate validity check for client certificates. | ||
173 | - skip_validity_check_for_client_cert: "${TCP_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" | 125 | + sip: |
126 | + # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡, | ||
127 | + # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 | ||
128 | + # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 | ||
129 | + # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 | ||
130 | + ip: ${GBT28181_SIP_IP:127.0.0.1} | ||
131 | + # [可选] 28181服务监听的端口 | ||
132 | + port: ${GBT28181_SIP_PORT:5060} | ||
133 | + #[可选] | ||
134 | + id: ${GBT28181_SIP_ID:51010700599000000001} | ||
135 | + # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) | ||
136 | + # 后两位为行业编码,定义参照附录D.3 | ||
137 | + # 3701020049标识山东济南历下区 信息行业接入 | ||
138 | + # [可选] | ||
139 | + domain: ${GBT28181_SIP_DOMAIN:5101070059} | ||
140 | + #[可选] | ||
141 | + password: ${GBT28181_SIP_PASSWORD:61332286} | ||
142 | + #zlm 默认服务器配置 | ||
143 | + media: | ||
144 | + id: ${GBT28181_MEDIA_GENERAL_ID:D2okJWKKaQ5bX7Va} | ||
145 | + # [必须修改] zlm服务器的内网IP | ||
146 | + ip: ${GBT28181_MEDIA_IP:127.0.0.1} | ||
147 | + # [必须修改] zlm服务器的http.port | ||
148 | + http-port: ${GBT28181_MEDIA_HTTP_PORT:28080} | ||
149 | + hook-ip: ${GBT28181_MEDIA_HOOK_IP:} | ||
150 | + stream-ip: ${GBT28181_MEDIA_STREAM_IP:} | ||
151 | + # [可选] zlm服务器的hook.admin_params=secret | ||
152 | + secret: ${GBT28181_MEDIA_API_SECRET:QhrTN7k6HcDnt0YyeolwHwiVYDgIHPMZ} | ||
153 | + # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 | ||
154 | + rtp: | ||
155 | + # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 | ||
156 | + enable: true | ||
157 | + # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 | ||
158 | + port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围 | ||
159 | + # [可选] 国标级联在此范围内选择端口发送媒体流, | ||
160 | + send-port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围 | ||
161 | + # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 | ||
162 | + record-assist-port: 0 | ||
163 | + defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:10}" | ||
164 | + | ||
174 | sessions: | 165 | sessions: |
175 | inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" | 166 | inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" |
176 | report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:3000}" | 167 | report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:3000}" |