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 | 36 | |
37 | 37 | @GetMapping("/start/{deviceId}/{channelId}") |
38 | 38 | @ApiOperation(value = "视频点播/预览") |
39 | -// @PreAuthorize("@check.checkPermissions({'SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:video:control:play'})") | |
40 | 39 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER')") |
41 | 40 | public DeferredResult<ResponseResult<StreamContentDTO>> startPlay( |
42 | 41 | @PathVariable("deviceId") String tbDeviceId, @PathVariable("channelId") String channelId) | ... | ... |
... | ... | @@ -3,16 +3,17 @@ package org.thingsboard.server.controller.yunteng.media; |
3 | 3 | import com.fasterxml.jackson.databind.JsonNode; |
4 | 4 | import io.swagger.annotations.Api; |
5 | 5 | import io.swagger.annotations.ApiOperation; |
6 | +import javax.servlet.http.HttpServletRequest; | |
6 | 7 | import lombok.RequiredArgsConstructor; |
7 | 8 | import lombok.extern.slf4j.Slf4j; |
9 | +import org.json.JSONObject; | |
8 | 10 | import org.springframework.web.bind.annotation.*; |
11 | +import org.springframework.web.context.request.async.DeferredResult; | |
9 | 12 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
10 | 13 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
11 | -import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
12 | 14 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; |
13 | 15 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; |
14 | 16 | import org.thingsboard.server.controller.BaseController; |
15 | -import org.thingsboard.server.dao.yunteng.service.TkDeviceService; | |
16 | 17 | import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService; |
17 | 18 | import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; |
18 | 19 | import org.thingsboard.server.service.yunteng.media.TkVideoControlService; |
... | ... | @@ -57,21 +58,140 @@ public class ZLMediaKitHookController extends BaseController { |
57 | 58 | @ResponseBody |
58 | 59 | @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") |
59 | 60 | @ApiOperation(value = "流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流") |
60 | - public JsonNode onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) throws ThingsboardException { | |
61 | + public JsonNode onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) | |
62 | + throws ThingsboardException { | |
61 | 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 | 66 | String channelId = result.get(FastIotConstants.ZLMediaBody.CHANNEL_ID).asText(); |
64 | 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 | 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 | 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 | 12 | * limitations under the License. |
15 | 13 | */ |
16 | 14 | package org.thingsboard.server.service.transport; |
... | ... | @@ -37,7 +35,6 @@ import java.util.concurrent.locks.ReentrantLock; |
37 | 35 | import java.util.stream.Collectors; |
38 | 36 | import lombok.RequiredArgsConstructor; |
39 | 37 | import lombok.extern.slf4j.Slf4j; |
40 | -import org.apache.zookeeper.Op; | |
41 | 38 | import org.springframework.stereotype.Service; |
42 | 39 | import org.thingsboard.common.util.JacksonUtil; |
43 | 40 | import org.thingsboard.server.cache.ota.OtaPackageDataCache; |
... | ... | @@ -74,13 +71,15 @@ import org.thingsboard.server.common.data.relation.EntityRelation; |
74 | 71 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
75 | 72 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
76 | 73 | import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; |
74 | +import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | |
77 | 75 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
78 | 76 | import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; |
79 | 77 | import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; |
78 | +import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; | |
80 | 79 | import org.thingsboard.server.common.data.yunteng.dto.sip.SipDeviceDTO; |
81 | -import org.thingsboard.server.common.data.yunteng.dto.sip.SsrcTransactionDTO; | |
82 | 80 | import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; |
83 | 81 | import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum; |
82 | +import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; | |
84 | 83 | import org.thingsboard.server.common.msg.EncryptionUtil; |
85 | 84 | import org.thingsboard.server.common.msg.TbMsg; |
86 | 85 | import org.thingsboard.server.common.msg.TbMsgDataType; |
... | ... | @@ -99,6 +98,7 @@ import org.thingsboard.server.dao.yunteng.entities.TkVideoChannelEntity; |
99 | 98 | import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService; |
100 | 99 | import org.thingsboard.server.dao.yunteng.service.TkDeviceService; |
101 | 100 | import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerNodeService; |
101 | +import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService; | |
102 | 102 | import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; |
103 | 103 | import org.thingsboard.server.gen.transport.TransportProtos; |
104 | 104 | import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; |
... | ... | @@ -126,650 +126,891 @@ import org.thingsboard.server.service.install.DefaultSystemDataLoaderService; |
126 | 126 | import org.thingsboard.server.service.profile.TbDeviceProfileCache; |
127 | 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 | 130 | @Slf4j |
133 | 131 | @Service |
134 | 132 | @TbCoreComponent |
135 | 133 | @RequiredArgsConstructor |
136 | 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 | 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 | 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 | 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 | 915 | String cameraCode = sip.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText(); |
754 | 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 | 721 | gbt28181: |
722 | 722 | # Enable/disable gbt28181 transport protocol. |
723 | 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 | 763 | tcp: |
725 | 764 | # Enable/disable tcp transport protocol. |
726 | 765 | enabled: "${TCP_ENABLED:true}" |
... | ... | @@ -1227,43 +1266,6 @@ logging: |
1227 | 1266 | frp: |
1228 | 1267 | server: |
1229 | 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 | 1270 | thingskit: |
1269 | 1271 | release: | ... | ... |
... | ... | @@ -680,6 +680,7 @@ message TransportApiRequestMsg { |
680 | 680 | //Thingskit function |
681 | 681 | ScriptProto script = 14; |
682 | 682 | Gbt28181RequestMsg gbt28181RequestMsg = 15; |
683 | + Gbt28181MediaServerMsg gbt28181MediaServerMsg = 16; | |
683 | 684 | } |
684 | 685 | |
685 | 686 | /* Response from ThingsBoard Core Service to Transport Service */ |
... | ... | @@ -698,6 +699,7 @@ message TransportApiResponseMsg { |
698 | 699 | //Thingskit function |
699 | 700 | repeated ScriptProto scriptsResponseMsg = 11; |
700 | 701 | Gbt28181ResponseMsg gbt28181ResponseMsg = 12; |
702 | + repeated Gbt28181MediaServerMsg gbt28181MediaServerMsg = 13; | |
701 | 703 | } |
702 | 704 | |
703 | 705 | /* Messages that are handled by ThingsBoard Core Service */ |
... | ... | @@ -826,5 +828,11 @@ message Gbt28181ResponseMsg{ |
826 | 828 | int64 entityIdMSB = 11; |
827 | 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 | 3 | import java.util.*; |
4 | 4 | import lombok.extern.slf4j.Slf4j; |
5 | 5 | import org.springframework.beans.factory.annotation.Autowired; |
6 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
7 | 6 | import org.springframework.stereotype.Component; |
8 | 7 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
9 | 8 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
... | ... | @@ -88,12 +87,14 @@ public class VideoStreamSessionManager { |
88 | 87 | public Optional<SsrcTransactionDTO> getSsrcTransaction(String fullKey) { |
89 | 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 | 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 | 1 | package org.thingsboard.server.common.data.yunteng.config.media; |
2 | 2 | |
3 | 3 | import lombok.Data; |
4 | -import org.springframework.boot.context.properties.ConfigurationProperties; | |
5 | 4 | import org.springframework.stereotype.Component; |
6 | 5 | |
7 | -@ConfigurationProperties(prefix = "user-settings") | |
8 | 6 | @Component |
9 | 7 | @Data |
10 | 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 | 3 | import io.swagger.annotations.ApiModelProperty; |
4 | 4 | import lombok.Data; |
5 | 5 | import lombok.EqualsAndHashCode; |
6 | -import org.springframework.util.ObjectUtils; | |
7 | -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | |
8 | 6 | import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; |
9 | 7 | |
10 | 8 | @EqualsAndHashCode(callSuper = true) |
... | ... | @@ -63,11 +61,11 @@ public class MediaServerDTO extends TenantDTO { |
63 | 61 | @ApiModelProperty(value = "流媒体服务器的状态") |
64 | 62 | private boolean status; |
65 | 63 | |
66 | - @ApiModelProperty(value = "多端口RTP收流端口范围") | |
64 | + @ApiModelProperty(value = "RTP收流端口范围") | |
67 | 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 | 70 | @ApiModelProperty(value = "assist服务端口") |
73 | 71 | private Integer recordAssistPort; |
... | ... | @@ -81,33 +79,7 @@ public class MediaServerDTO extends TenantDTO { |
81 | 79 | @ApiModelProperty(value = "当前使用到的端口") |
82 | 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 | 1 | package org.thingsboard.server.common.data.yunteng.dto.sip; |
2 | 2 | |
3 | 3 | import io.swagger.annotations.ApiModelProperty; |
4 | +import java.io.Serializable; | |
4 | 5 | import lombok.Data; |
5 | 6 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
6 | 7 | |
7 | -import java.io.Serializable; | |
8 | - | |
9 | 8 | @Data |
10 | 9 | public class SipDeviceDTO implements Serializable { |
11 | 10 | @ApiModelProperty(value = "设备国标编号") |
... | ... | @@ -37,6 +36,7 @@ public class SipDeviceDTO implements Serializable { |
37 | 36 | |
38 | 37 | @ApiModelProperty(value = "是否开启ssrc校验,默认关闭,开启可以防止串流") |
39 | 38 | private boolean ssrcCheck = true; |
39 | + | |
40 | 40 | @ApiModelProperty(value = "生产厂商") |
41 | 41 | private String manufacturer; |
42 | 42 | |
... | ... | @@ -48,12 +48,13 @@ public class SipDeviceDTO implements Serializable { |
48 | 48 | |
49 | 49 | @ApiModelProperty(value = "固件版本") |
50 | 50 | private String firmware; |
51 | + | |
51 | 52 | public Integer getStreamModeForParam() { |
52 | 53 | if (FastIotConstants.StreamMode.UDP.equalsIgnoreCase(streamMode)) { |
53 | 54 | return 0; |
54 | - }else if (FastIotConstants.StreamMode.TCP_PASSIVE.equalsIgnoreCase(streamMode)) { | |
55 | + } else if (FastIotConstants.StreamMode.TCP_PASSIVE.equalsIgnoreCase(streamMode)) { | |
55 | 56 | return 1; |
56 | - }else if (FastIotConstants.StreamMode.TCP_ACTIVE.equalsIgnoreCase(streamMode)) { | |
57 | + } else if (FastIotConstants.StreamMode.TCP_ACTIVE.equalsIgnoreCase(streamMode)) { | |
57 | 58 | return 2; |
58 | 59 | } |
59 | 60 | return 0; | ... | ... |
... | ... | @@ -2,6 +2,8 @@ package org.thingsboard.server.common.data.yunteng.utils; |
2 | 2 | |
3 | 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 | 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 | 10 | import javax.sip.address.SipURI; |
11 | 11 | import javax.sip.header.*; |
12 | 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 | 18 | @Autowired private SipConfig sipConfig; |
21 | 19 | @Autowired protected ThingsKitVersionConfig thingsKitVersionConfig; |
22 | 20 | |
... | ... | @@ -41,7 +39,7 @@ public class AbstractSIPRequestProcess { |
41 | 39 | ViaHeader viaHeader = |
42 | 40 | sipFactory |
43 | 41 | .createHeaderFactory() |
44 | - .createViaHeader(SipLayer.getLocalIp(localIp), sipConfig.getPort(), transport, viaTag); | |
42 | + .createViaHeader(SipTransportService.getLocalIp(localIp), sipConfig.getPort(), transport, viaTag); | |
45 | 43 | viaHeader.setRPort(); |
46 | 44 | viaHeaders.add(viaHeader); |
47 | 45 | return viaHeaders; |
... | ... | @@ -78,7 +76,7 @@ public class AbstractSIPRequestProcess { |
78 | 76 | throws PeerUnavailableException, ParseException { |
79 | 77 | SipURI sipUri = |
80 | 78 | buildRequestLineSipUri( |
81 | - sipConfig.getId(), SipLayer.getLocalIp(localIp) + ":" + sipConfig.getPort()); | |
79 | + sipConfig.getId(), SipTransportService.getLocalIp(localIp) + ":" + sipConfig.getPort()); | |
82 | 80 | Address concatAddress = sipFactory.createAddressFactory().createAddress(sipUri); |
83 | 81 | return sipFactory.createHeaderFactory().createContactHeader(concatAddress); |
84 | 82 | } | ... | ... |
... | ... | @@ -15,12 +15,16 @@ import javax.sip.address.SipURI; |
15 | 15 | import javax.sip.header.*; |
16 | 16 | import javax.sip.message.Request; |
17 | 17 | import javax.sip.message.Response; |
18 | + | |
19 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
18 | 20 | import org.springframework.stereotype.Component; |
19 | 21 | import org.thingsboard.server.common.data.yunteng.dto.sip.SipMessageHeaderDTO; |
20 | 22 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; |
21 | 23 | import org.thingsboard.server.transport.util.TKSipUtils; |
22 | 24 | |
23 | 25 | @Component |
26 | +@ConditionalOnExpression( | |
27 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | |
24 | 28 | public class SIPRequestHeaderProcess extends AbstractSIPRequestProcess { |
25 | 29 | public Request createMessageRequest( |
26 | 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 | 3 | import gov.nist.javax.sip.SipProviderImpl; |
4 | 4 | import java.text.ParseException; |
... | ... | @@ -11,15 +11,18 @@ import javax.sip.message.Request; |
11 | 11 | import javax.sip.message.Response; |
12 | 12 | import lombok.extern.slf4j.Slf4j; |
13 | 13 | import org.springframework.beans.factory.annotation.Autowired; |
14 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
14 | 15 | import org.springframework.stereotype.Component; |
15 | 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 | 19 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; |
19 | 20 | import org.thingsboard.server.transport.util.TKSipUtils; |
20 | 21 | |
21 | 22 | /** 发送SIP信息 */ |
22 | 23 | @Component |
24 | +@ConditionalOnExpression( | |
25 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | |
23 | 26 | @Slf4j |
24 | 27 | public class SIPSender { |
25 | 28 | |
... | ... | @@ -80,7 +83,7 @@ public class SIPSender { |
80 | 83 | } |
81 | 84 | |
82 | 85 | SipProviderImpl sipProvider = |
83 | - TCP.equals(transport) ? SipLayer.getTcpSipProvider(ip) : SipLayer.getUdpSipProvider(ip); | |
86 | + TCP.equals(transport) ? SipTransportService.getTcpSipProvider(ip) : SipTransportService.getUdpSipProvider(ip); | |
84 | 87 | if (sipProvider == null) { |
85 | 88 | log.error("[发送信息失败] 未找到{}://{}的监听信息", transport, ip); |
86 | 89 | return; |
... | ... | @@ -94,23 +97,23 @@ public class SIPSender { |
94 | 97 | |
95 | 98 | public CallIdHeader getNewCallIdHeader(String ip, String transport) { |
96 | 99 | if (ObjectUtils.isEmpty(transport)) { |
97 | - return SipLayer.getUdpSipProvider().getNewCallId(); | |
100 | + return SipTransportService.getUdpSipProvider().getNewCallId(); | |
98 | 101 | } |
99 | 102 | SipProviderImpl sipProvider; |
100 | 103 | if (ObjectUtils.isEmpty(ip)) { |
101 | 104 | sipProvider = |
102 | 105 | transport.equalsIgnoreCase(TCP) |
103 | - ? SipLayer.getTcpSipProvider() | |
104 | - : SipLayer.getUdpSipProvider(); | |
106 | + ? SipTransportService.getTcpSipProvider() | |
107 | + : SipTransportService.getUdpSipProvider(); | |
105 | 108 | } else { |
106 | 109 | sipProvider = |
107 | 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 | 115 | if (sipProvider == null) { |
113 | - sipProvider = SipLayer.getUdpSipProvider(); | |
116 | + sipProvider = SipTransportService.getUdpSipProvider(); | |
114 | 117 | } |
115 | 118 | |
116 | 119 | if (sipProvider != null) { | ... | ... |
... | ... | @@ -13,8 +13,7 @@ import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
13 | 13 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
14 | 14 | import org.thingsboard.server.common.data.yunteng.dto.sip.*; |
15 | 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 | 17 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; |
19 | 18 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; |
20 | 19 | import org.thingsboard.server.transport.util.TKSipUtils; |
... | ... | @@ -41,11 +40,11 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { |
41 | 40 | sessionCtx.getCameraCode()); |
42 | 41 | CallIdHeader callIdHeader = |
43 | 42 | sipSender.getNewCallIdHeader( |
44 | - SipLayer.getLocalIp(sessionCtx.getLocalIp()), sessionCtx.getTransport()); | |
43 | + SipTransportService.getLocalIp(sessionCtx.getLocalIp()), sessionCtx.getTransport()); | |
45 | 44 | Request request = |
46 | 45 | headerProvider.createMessageRequest( |
47 | 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 | 50 | @Override |
... | ... | @@ -63,13 +62,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { |
63 | 62 | deviceSessionCtx.getCameraCode()); |
64 | 63 | CallIdHeader callIdHeader = |
65 | 64 | sipSender.getNewCallIdHeader( |
66 | - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); | |
65 | + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); | |
67 | 66 | Request request = |
68 | 67 | headerProvider.createMessageRequest( |
69 | 68 | deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); |
70 | 69 | |
71 | 70 | sipSender.transmitRequest( |
72 | - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), request, errorEvent); | |
71 | + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), request, errorEvent); | |
73 | 72 | } |
74 | 73 | |
75 | 74 | @Override |
... | ... | @@ -86,12 +85,12 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { |
86 | 85 | ptzCmd); |
87 | 86 | CallIdHeader callIdHeader = |
88 | 87 | sipSender.getNewCallIdHeader( |
89 | - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); | |
88 | + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); | |
90 | 89 | Request request = |
91 | 90 | headerProvider.createMessageRequest( |
92 | 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 | 96 | @Override |
... | ... | @@ -110,13 +109,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { |
110 | 109 | |
111 | 110 | CallIdHeader callIdHeader = |
112 | 111 | sipSender.getNewCallIdHeader( |
113 | - SipLayer.getLocalIp(devSession.getLocalIp()), devSession.getTransport()); | |
112 | + SipTransportService.getLocalIp(devSession.getLocalIp()), devSession.getTransport()); | |
114 | 113 | Request request = |
115 | 114 | headerProvider.createInviteRequest( |
116 | 115 | devSession, sipMessageHeaderDTO, channelId, content, callIdHeader, ssrc); |
117 | 116 | |
118 | 117 | sipSender.transmitRequest( |
119 | - SipLayer.getLocalIp(devSession.getLocalIp()), request, errorEvent, okEvent); | |
118 | + SipTransportService.getLocalIp(devSession.getLocalIp()), request, errorEvent, okEvent); | |
120 | 119 | } |
121 | 120 | |
122 | 121 | @Override |
... | ... | @@ -144,7 +143,7 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { |
144 | 143 | headerDTO.getViaTag(), |
145 | 144 | headerDTO.getFromTag(), |
146 | 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 | 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 | 3 | import lombok.Data; |
4 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
4 | 5 | import org.springframework.boot.context.properties.ConfigurationProperties; |
5 | 6 | import org.springframework.stereotype.Component; |
6 | 7 | |
7 | -@ConfigurationProperties(prefix = "sip") | |
8 | +@ConfigurationProperties(prefix = "transport.gbt28181.sip") | |
8 | 9 | @Component |
10 | +@ConditionalOnExpression( | |
11 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | |
9 | 12 | @Data |
10 | 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 | 3 | import lombok.Data; |
4 | 4 | import org.springframework.beans.factory.annotation.Value; |
5 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
5 | 6 | import org.springframework.stereotype.Component; |
6 | 7 | |
7 | 8 | @Component |
9 | +@ConditionalOnExpression( | |
10 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | |
8 | 11 | @Data |
9 | 12 | public class ThingsKitVersionConfig { |
10 | 13 | @Value("${thingskit.release.version}") | ... | ... |
... | ... | @@ -13,12 +13,15 @@ import javax.sip.header.CallIdHeader; |
13 | 13 | import javax.sip.message.Response; |
14 | 14 | import org.slf4j.Logger; |
15 | 15 | import org.slf4j.LoggerFactory; |
16 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
16 | 17 | import org.springframework.scheduling.annotation.Scheduled; |
17 | 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 | 21 | /** SIP订阅信息 */ |
21 | 22 | @Component |
23 | +@ConditionalOnExpression( | |
24 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | |
22 | 25 | public class SipSubscribe { |
23 | 26 | |
24 | 27 | private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class); | ... | ... |
... | ... | @@ -36,8 +36,6 @@ import javax.sip.header.HeaderFactory; |
36 | 36 | import javax.sip.header.WWWAuthenticateHeader; |
37 | 37 | import javax.sip.message.Request; |
38 | 38 | import javax.sip.message.Response; |
39 | -import org.slf4j.Logger; | |
40 | -import org.slf4j.LoggerFactory; | |
41 | 39 | |
42 | 40 | /** Implements the HTTP digest authentication method server side functionality. */ |
43 | 41 | public class DigestServerAuthenticationHelper { |
... | ... | @@ -99,6 +97,7 @@ public class DigestServerAuthenticationHelper { |
99 | 97 | } |
100 | 98 | return response; |
101 | 99 | } |
100 | + | |
102 | 101 | /** |
103 | 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 | 6 | public class RemoteAddressInfo { |
4 | 7 | private String ip; |
5 | 8 | private int port; |
... | ... | @@ -8,20 +11,4 @@ public class RemoteAddressInfo { |
8 | 11 | this.ip = ip; |
9 | 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 | 7 | import java.util.concurrent.ConcurrentHashMap; |
8 | 8 | import java.util.concurrent.TimeUnit; |
9 | 9 | |
10 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; | |
10 | 11 | import org.springframework.scheduling.annotation.Scheduled; |
11 | 12 | import org.springframework.stereotype.Component; |
12 | 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 | 17 | import org.thingsboard.server.common.data.yunteng.enums.CatalogDataStatusEnum; |
17 | 18 | |
18 | 19 | @Component |
20 | +@ConditionalOnExpression( | |
21 | + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") | |
19 | 22 | public class CatalogDataCatch { |
20 | 23 | |
21 | 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 | 3 | import io.netty.handler.ssl.SslHandler; |
5 | -import java.net.InetSocketAddress; | |
6 | 4 | import java.util.concurrent.Executors; |
7 | 5 | import java.util.concurrent.ScheduledExecutorService; |
8 | 6 | import java.util.concurrent.atomic.AtomicInteger; |
... | ... | @@ -10,13 +8,11 @@ import javax.annotation.PostConstruct; |
10 | 8 | import lombok.Getter; |
11 | 9 | import lombok.Setter; |
12 | 10 | import lombok.extern.slf4j.Slf4j; |
13 | -import org.springframework.beans.factory.annotation.Autowired; | |
14 | 11 | import org.springframework.beans.factory.annotation.Value; |
15 | 12 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
16 | 13 | import org.springframework.stereotype.Component; |
17 | 14 | import org.thingsboard.common.util.ThingsBoardThreadFactory; |
18 | 15 | import org.thingsboard.server.common.transport.TransportContext; |
19 | -import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor; | |
20 | 16 | |
21 | 17 | @Slf4j |
22 | 18 | @Component |
... | ... | @@ -24,8 +20,6 @@ import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor; |
24 | 20 | "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") |
25 | 21 | public class GbtTransportContext extends TransportContext { |
26 | 22 | |
27 | - /** 注入多种数据协议处理器,例如:modbus等 */ | |
28 | - @Getter @Autowired private GbtTransportAdaptor jsonAdaptor; | |
29 | 23 | |
30 | 24 | @Getter |
31 | 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 | 11 | * express or implied. See the License for the specific language governing permissions and |
12 | 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 | 16 | import gov.nist.javax.sip.SipProviderImpl; |
17 | 17 | import gov.nist.javax.sip.SipStackImpl; |
... | ... | @@ -26,20 +26,20 @@ import org.springframework.stereotype.Service; |
26 | 26 | import org.springframework.util.ObjectUtils; |
27 | 27 | import org.thingsboard.server.common.data.DataConstants; |
28 | 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 | 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 | 38 | @Slf4j |
38 | -public class SipLayer implements TbTransportService { | |
39 | +public class SipTransportService implements TbTransportService { | |
39 | 40 | private static final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); |
40 | 41 | private static final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); |
41 | - @Autowired | |
42 | - private SIPProvider sipProvider; | |
42 | + @Autowired private SIPProvider sipProvider; | |
43 | 43 | |
44 | 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 | 3 | import java.util.EventObject; |
4 | 4 | import javax.sip.Dialog; |
5 | +import lombok.Getter; | |
6 | +import lombok.Setter; | |
5 | 7 | |
8 | +@Getter | |
9 | +@Setter | |
6 | 10 | public class DeviceNotFoundEvent extends EventObject { |
7 | 11 | |
8 | 12 | private String callId; |
... | ... | @@ -16,12 +20,4 @@ public class DeviceNotFoundEvent extends EventObject { |
16 | 20 | public DeviceNotFoundEvent(Dialog dialog) { |
17 | 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 | 3 | import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED; |
4 | 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 | 40 | import org.thingsboard.server.common.data.StringUtils; |
41 | 41 | import org.thingsboard.server.common.data.id.DeviceId; |
42 | 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 | 43 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
46 | 44 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
47 | 45 | import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; |
... | ... | @@ -58,11 +56,16 @@ import org.thingsboard.server.common.transport.auth.SessionInfoCreator; |
58 | 56 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
59 | 57 | import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; |
60 | 58 | import org.thingsboard.server.gen.transport.TransportProtos; |
59 | +import org.thingsboard.server.transport.gbt28181.session.GbtTransportContext; | |
61 | 60 | import org.thingsboard.server.transport.cmd.SIPRequestHeaderProcess; |
62 | 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 | 64 | import org.thingsboard.server.transport.gbt28181.*; |
64 | 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 | 69 | import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; |
67 | 70 | import org.thingsboard.server.transport.util.TKSipUtils; |
68 | 71 | import org.thingsboard.server.transport.util.TKXmlUtil; |
... | ... | @@ -81,6 +84,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
81 | 84 | |
82 | 85 | private final SIPRequestHeaderProcess headerProvider; |
83 | 86 | private final SipConfig sipConfig; |
87 | + private final MediaConfig mediaConfig; | |
84 | 88 | private final UserSetting userSetting; |
85 | 89 | private final TKSipCommanderService commanderService; |
86 | 90 | private final DataDecodingEncodingService encodingService; |
... | ... | @@ -93,7 +97,9 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
93 | 97 | |
94 | 98 | @Getter |
95 | 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 | 103 | private static final Map<String, ISIPRequestProcessor> requestProcessorMap = |
98 | 104 | new ConcurrentHashMap<>(); |
99 | 105 | private static final Map<String, ISIPResponseProcessor> responseProcessorMap = |
... | ... | @@ -101,6 +107,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
101 | 107 | private static ITimeoutProcessor timeoutProcessor; |
102 | 108 | |
103 | 109 | private final SipSubscribe sipSubscribe; |
110 | + | |
104 | 111 | /** |
105 | 112 | * 添加 request订阅 |
106 | 113 | * |
... | ... | @@ -159,7 +166,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
159 | 166 | CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); |
160 | 167 | String methodName = cseqHeader.getMethod(); |
161 | 168 | SIPResponse request = (SIPResponse) responseEvent.getResponse(); |
162 | - log.debug( | |
169 | + log.info( | |
163 | 170 | "收到ResponseEvent,方法类型【{}】,状态码【{}】,事件内容【{}】", |
164 | 171 | methodName, |
165 | 172 | status, |
... | ... | @@ -178,8 +185,11 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
178 | 185 | default: |
179 | 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 | 193 | if (callIdHeader != null) { |
184 | 194 | SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); |
185 | 195 | if (subscribe != null) { |
... | ... | @@ -192,20 +202,26 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
192 | 202 | } else if ((status >= Response.TRYING) && (status < Response.OK)) { |
193 | 203 | // 增加其它无需回复的响应,如101、180等 |
194 | 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 | 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 | 235 | public void processRequest(RequestEvent requestEvent) { |
220 | 236 | String methodName = requestEvent.getRequest().getMethod(); |
221 | 237 | SIPRequest request = (SIPRequest) requestEvent.getRequest(); |
222 | - log.debug( | |
238 | + log.info( | |
223 | 239 | "收到RequestEvent,方法类型【{}】,事件内容【{}】", |
224 | 240 | methodName, |
225 | 241 | request.getRawContent() == null ? null : new String(request.getRawContent())); |
... | ... | @@ -307,14 +323,15 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
307 | 323 | */ |
308 | 324 | void processResponseMessage(GbtDeviceSessionCtx ctx, ResponseEvent msg) {} |
309 | 325 | |
310 | - private String cameraAddress(SIPRequest request){ | |
326 | + private String cameraAddress(SIPRequest request) { | |
311 | 327 | RemoteAddressInfo remoteAddressInfo = |
312 | - TKSipUtils.getRemoteAddressFromRequest( | |
313 | - request, userSetting.getSipUseSourceIpAsRemoteAddress()); | |
328 | + TKSipUtils.getRemoteAddressFromRequest( | |
329 | + request, userSetting.getSipUseSourceIpAsRemoteAddress()); | |
314 | 330 | String hostAddress = remoteAddressInfo.getIp(); |
315 | 331 | int remotePort = remoteAddressInfo.getPort(); |
316 | 332 | return hostAddress + ":" + remotePort; |
317 | 333 | } |
334 | + | |
318 | 335 | /** |
319 | 336 | * 处理请求事件的MESSAGE消息,根据XML数据的根节点名称进行分发 |
320 | 337 | * |
... | ... | @@ -342,7 +359,8 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
342 | 359 | } |
343 | 360 | if (ctx != null) { |
344 | 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 | 364 | deviceSessions.remove(ctx.getCameraCode()); |
347 | 365 | responseAck(request, Response.OK); |
348 | 366 | return; |
... | ... | @@ -454,7 +472,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
454 | 472 | transportService.deregisterSession(ds.getSessionInfo()); |
455 | 473 | transportService.process(ds.getSessionInfo(), SESSION_EVENT_MSG_CLOSED, null); |
456 | 474 | try { |
457 | - cameraResponseRequest(ds, request, null,null); | |
475 | + cameraResponseRequest(ds, request, null, null); | |
458 | 476 | } catch (InvalidArgumentException | ParseException | SipException e) { |
459 | 477 | throw new RuntimeException(e); |
460 | 478 | } |
... | ... | @@ -515,24 +533,25 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
515 | 533 | case DeviceInfo: |
516 | 534 | SipDeviceDTO cameraInfoDTO = TKXmlUtil.cameraInfoBuilder(rootElement); |
517 | 535 | cameraInfoDTO.setHostAddress(request.getViaHost() + ":" + request.getViaPort()); |
536 | + cameraInfoDTO.setMediaServerId(mediaConfig.getMediaServerId()); | |
518 | 537 | byte[] cameraMsgBytes = encodingService.encode(cameraInfoDTO); |
519 | 538 | msgBuilder.setContext(ByteString.copyFrom(cameraMsgBytes)); |
520 | 539 | break; |
521 | 540 | case Catalog: |
522 | 541 | List<VideoChanelDTO> channelDTO = TKXmlUtil.channelInfoBuilder(devSession, rootElement); |
523 | 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 | 555 | byte[] channaelMsgBytes = encodingService.encode(deviceNewChanel.get(cameraCode)); |
537 | 556 | msgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes)); |
538 | 557 | deviceNewChanel.remove(cameraCode); |
... | ... | @@ -644,7 +663,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
644 | 663 | return; |
645 | 664 | } |
646 | 665 | DeviceProfile profile = msg.getDeviceProfile(); |
647 | - if(profile.getTransportType() != DeviceTransportType.GBT28181){ | |
666 | + if (profile.getTransportType() != DeviceTransportType.GBT28181) { | |
648 | 667 | return; |
649 | 668 | } |
650 | 669 | GbtDeviceSessionCtx deviceSessionCtx = |
... | ... | @@ -698,12 +717,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
698 | 717 | .build(); |
699 | 718 | commanderService.queryDeviceInfo(deviceSessionCtx, deviceInfoHeader); |
700 | 719 | int sn = (int) ((Math.random() * 9 + 1) * 100000); |
701 | - rpcCameraChannel(deviceSessionCtx,sn); | |
720 | + rpcCameraChannel(deviceSessionCtx, sn); | |
702 | 721 | } catch (InvalidArgumentException | SipException | ParseException e) { |
703 | 722 | throw new RuntimeException(e); |
704 | 723 | } |
705 | 724 | |
706 | - // transportService.getCallbackExecutor().execute(() -> | |
725 | + // transportService.getCallbackExecutor().execute(() -> | |
707 | 726 | // processQueueMessage(ctx)); //this callback will execute in Producer worker thread and |
708 | 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 | 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 | 808 | |
793 | 809 | String channelId = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.CHANNEL_ID); |
794 | 810 | |
795 | - switch (VideoMethodEnum.valueOf(methodType)){ | |
811 | + switch (VideoMethodEnum.valueOf(methodType)) { | |
796 | 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 | 817 | break; |
800 | 818 | case INVITE: |
801 | 819 | JsonNode mediaInform = rpcBody.get(FastIotConstants.ZLMediaBody.MEDIA); |
... | ... | @@ -807,64 +825,81 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent |
807 | 825 | String stream = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.SSRCINFO_STREAM); |
808 | 826 | |
809 | 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 | 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 | 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 | 900 | break; |
866 | 901 | case MESSAGE: |
867 | - toDeviceRpcMessage(devSession,channelId,rpcBody); | |
902 | + toDeviceRpcMessage(devSession, channelId, rpcBody); | |
868 | 903 | break; |
869 | 904 | } |
870 | 905 | } catch (InvalidArgumentException | SipException | ParseException e) { |
... | ... | @@ -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 | 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 | 920 | String msgType = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_TYPE).asText(); |
884 | - switch (VideoXmlEnum.valueOf(msgType)){ | |
921 | + switch (VideoXmlEnum.valueOf(msgType)) { | |
885 | 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 | 927 | break; |
889 | 928 | case Query: |
890 | 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 | 937 | * @throws InvalidArgumentException |
898 | 938 | * @throws SipException |
899 | 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 | 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 | 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 | 959 | private String rpcParamVal(JsonNode rpcBody, String key) { |
918 | 960 | if (rpcBody.has(key)) { |
919 | 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 | 3 | import gov.nist.javax.sip.message.SIPRequest; |
4 | 4 | import gov.nist.javax.sip.message.SIPResponse; |
... | ... | @@ -20,7 +20,7 @@ import org.dom4j.DocumentException; |
20 | 20 | import org.dom4j.Element; |
21 | 21 | import org.dom4j.io.SAXReader; |
22 | 22 | import org.springframework.beans.factory.annotation.Autowired; |
23 | -import org.thingsboard.server.transport.SIPSender; | |
23 | +import org.thingsboard.server.transport.cmd.SIPSender; | |
24 | 24 | import org.thingsboard.server.transport.util.TKSipUtils; |
25 | 25 | |
26 | 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 | 3 | import javax.sip.TimeoutEvent; |
4 | 4 | import javax.sip.header.CallIdHeader; |
... | ... | @@ -8,8 +8,6 @@ import org.springframework.beans.factory.InitializingBean; |
8 | 8 | import org.springframework.beans.factory.annotation.Autowired; |
9 | 9 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; |
10 | 10 | import org.springframework.stereotype.Component; |
11 | -import org.thingsboard.server.transport.gbt28181.ITimeoutProcessor; | |
12 | -import org.thingsboard.server.transport.SIPProcessorObserver; | |
13 | 11 | import org.thingsboard.server.transport.gbt28181.SipSubscribe; |
14 | 12 | |
15 | 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 | 13 | import lombok.Setter; |
14 | 14 | import lombok.extern.slf4j.Slf4j; |
15 | 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 | 19 | * @author Andrew Shvayka | ... | ... |
... | ... | @@ -10,10 +10,10 @@ import javax.sip.SipFactory; |
10 | 10 | import javax.sip.header.UserAgentHeader; |
11 | 11 | import org.apache.commons.lang3.RandomStringUtils; |
12 | 12 | import org.springframework.util.ObjectUtils; |
13 | -import org.thingsboard.server.common.data.yunteng.config.media.ThingsKitVersionConfig; | |
14 | 13 | import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; |
15 | 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 | 18 | public class TKSipUtils { |
19 | 19 | public static String getNewMessageViaBranchTag() { |
... | ... | @@ -55,14 +55,14 @@ public class TKSipUtils { |
55 | 55 | builder.append(strTmp, 0, 2); |
56 | 56 | strTmp = String.format("%X", combineCode2); |
57 | 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 | 61 | strTmp = String.format("%02X", checkCode); |
61 | 62 | builder.append(strTmp, 0, 2); |
62 | 63 | return builder.toString(); |
63 | 64 | } |
64 | 65 | |
65 | - | |
66 | 66 | public static UserAgentHeader createUserAgentHeader(ThingsKitVersionConfig config) |
67 | 67 | throws PeerUnavailableException, ParseException { |
68 | 68 | List<String> agentParam = new ArrayList<>(); | ... | ... |
1 | 1 | /** |
2 | 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 | 12 | * limitations under the License. |
15 | 13 | */ |
16 | 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 | 19 | import org.thingsboard.server.common.data.DeviceProfile; |
19 | 20 | import org.thingsboard.server.common.data.DeviceTransportType; |
20 | 21 | import org.thingsboard.server.common.data.rpc.RpcStatus; |
... | ... | @@ -40,10 +41,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRespon |
40 | 41 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; |
41 | 42 | import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; |
42 | 43 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
43 | -import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; | |
44 | 44 | import org.thingsboard.server.gen.transport.TransportProtos.PostEventMsg; |
45 | +import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; | |
45 | 46 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
46 | 47 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
48 | +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | |
47 | 49 | import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg; |
48 | 50 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
49 | 51 | import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; |
... | ... | @@ -57,104 +59,140 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre |
57 | 59 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; |
58 | 60 | import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; |
59 | 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 | 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 | 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 | 12 | * limitations under the License. |
15 | 13 | */ |
16 | 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 | 18 | import com.google.common.util.concurrent.Futures; |
19 | 19 | import com.google.common.util.concurrent.ListenableFuture; |
20 | 20 | import com.google.common.util.concurrent.MoreExecutors; |
21 | 21 | import com.google.gson.Gson; |
22 | 22 | import com.google.gson.JsonObject; |
23 | 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 | 38 | import lombok.Getter; |
25 | 39 | import lombok.extern.slf4j.Slf4j; |
26 | 40 | import org.springframework.beans.factory.annotation.Value; |
27 | 41 | import org.springframework.context.ApplicationEventPublisher; |
42 | +import org.springframework.core.annotation.Order; | |
28 | 43 | import org.springframework.scheduling.annotation.Scheduled; |
29 | 44 | import org.springframework.stereotype.Service; |
30 | 45 | import org.thingsboard.common.util.ThingsBoardExecutors; |
... | ... | @@ -79,13 +94,13 @@ import org.thingsboard.server.common.transport.yunteng.ScriptUpdatedEvent; |
79 | 94 | import org.thingsboard.server.gen.transport.TransportProtos; |
80 | 95 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; |
81 | 96 | import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; |
97 | +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | |
82 | 98 | import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; |
83 | 99 | import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; |
84 | 100 | import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; |
85 | 101 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; |
86 | 102 | import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; |
87 | 103 | import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; |
88 | -import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto; | |
89 | 104 | import org.thingsboard.server.queue.TbQueueCallback; |
90 | 105 | import org.thingsboard.server.queue.TbQueueConsumer; |
91 | 106 | import org.thingsboard.server.queue.TbQueueMsgMetadata; |
... | ... | @@ -102,1204 +117,1604 @@ import org.thingsboard.server.queue.usagestats.TbApiUsageClient; |
102 | 117 | import org.thingsboard.server.queue.util.AfterStartUp; |
103 | 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 | 121 | @Slf4j |
126 | 122 | @Service |
123 | +@Order(value = 3) | |
127 | 124 | @TbTransportComponent |
128 | 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 | 474 | result.credentials(msg.getCredentialsBody()); |
404 | 475 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); |
405 | 476 | result.deviceInfo(tdi); |
406 | 477 | ByteString profileBody = msg.getProfileBody(); |
407 | 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 | 518 | result.credentials(msg.getCredentialsBody()); |
431 | 519 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); |
432 | 520 | result.deviceInfo(tdi); |
433 | 521 | ByteString profileBody = msg.getProfileBody(); |
434 | 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 | 569 | TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); |
458 | 570 | result.deviceInfo(tdi); |
459 | 571 | ByteString profileBody = msg.getProfileBody(); |
460 | 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 | 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 | 710 | metaData.putValue("deviceName", sessionInfo.getDeviceName()); |
613 | 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 | 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 | 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 | 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 | 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 | 4 | import lombok.extern.slf4j.Slf4j; |
5 | 5 | import org.springframework.beans.factory.annotation.Autowired; |
6 | 6 | import org.springframework.stereotype.Component; |
7 | -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig; | |
8 | 7 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
9 | 8 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
10 | 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 | 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 | 21 | private static final String SSRC_INFO_KEY = "TK_SSRC_INFO_"; |
... | ... | @@ -24,26 +23,29 @@ public class SSRCFactory { |
24 | 23 | private final String cacheName = FastIotConstants.MediaServerKey.MEDIA_SERVER_CACHE_NAME; |
25 | 24 | @Autowired private CacheUtils cacheUtils; |
26 | 25 | |
27 | - @Autowired private SipConfig sipConfig; | |
28 | - | |
29 | 26 | @Autowired private UserSetting userSetting; |
30 | 27 | |
31 | 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 | 3 | import java.text.ParseException; |
4 | 4 | import java.util.*; |
5 | 5 | import java.util.concurrent.ConcurrentHashMap; |
6 | - | |
7 | 6 | import lombok.RequiredArgsConstructor; |
8 | 7 | import lombok.extern.slf4j.Slf4j; |
9 | 8 | import org.springframework.stereotype.Component; |
9 | +import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | |
10 | 10 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; |
11 | 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 | 12 | import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; |
14 | -import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; | |
15 | 13 | import org.thingsboard.server.dao.yunteng.service.media.TkCacheStorageService; |
16 | 14 | |
17 | 15 | @Component |
... | ... | @@ -24,31 +22,36 @@ public class ZLMMediaListManager { |
24 | 22 | private final ZLMRTPServerFactory zlmrtpServerFactory; |
25 | 23 | private final TkCacheStorageService tkCacheStorageService; |
26 | 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 | 55 | public void sendStreamEvent(String app, String stream, String mediaServerId) { |
53 | 56 | MediaServerDTO mediaServerItem = tkCacheStorageService.findInfoByMediaServerId(mediaServerId); |
54 | 57 | // 查看推流状态 | ... | ... |
... | ... | @@ -75,7 +75,8 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { |
75 | 75 | } |
76 | 76 | |
77 | 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 | 80 | if (mediaServerItem == null) { |
80 | 81 | callback.run(false); |
81 | 82 | return; |
... | ... | @@ -85,13 +86,13 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { |
85 | 86 | |
86 | 87 | @Override |
87 | 88 | public void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig) { |
89 | + String serverId = zlmServerConfig.getGeneralMediaServerId(); | |
88 | 90 | MediaServerDTO serverItem = |
89 | - tkMediaServerService.findMediaServerInfoById( | |
90 | - zlmServerConfig.getTenantId(), zlmServerConfig.getGeneralMediaServerId()); | |
91 | + tkMediaServerService.findMediaServerInfoById(zlmServerConfig.getTenantId(), serverId); | |
91 | 92 | if (serverItem == null) { |
92 | 93 | log.warn( |
93 | 94 | "[未注册的zlm] 拒接接入:{}来自{}:{}", |
94 | - zlmServerConfig.getGeneralMediaServerId(), | |
95 | + serverId, | |
95 | 96 | zlmServerConfig.getIp(), |
96 | 97 | zlmServerConfig.getHttpPort()); |
97 | 98 | log.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致"); |
... | ... | @@ -99,7 +100,7 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { |
99 | 100 | } else { |
100 | 101 | log.info( |
101 | 102 | "[ZLM] 正在连接 : {} -> {}:{}", |
102 | - zlmServerConfig.getGeneralMediaServerId(), | |
103 | + serverId, | |
103 | 104 | zlmServerConfig.getIp(), |
104 | 105 | zlmServerConfig.getHttpPort()); |
105 | 106 | } |
... | ... | @@ -134,14 +135,14 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { |
134 | 135 | zlmServerConfig.getHttpPort()); |
135 | 136 | return; |
136 | 137 | } |
137 | - tkMediaServerService.saveOrUpdateMediaServer(serverItem); | |
138 | + tkMediaServerService.updateMediaServer(serverItem); | |
138 | 139 | String key = |
139 | 140 | FastIotConstants.MediaServerKey.MEDIA_SERVER_PREFIX |
140 | 141 | + userSetting.getServerId() |
141 | 142 | + "_" |
142 | - + zlmServerConfig.getGeneralMediaServerId(); | |
143 | + + serverId; | |
143 | 144 | if (ssrcFactory.hasMediaServerSSRC(serverItem.getMediaServerId())) { |
144 | - ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); | |
145 | + ssrcFactory.initMediaServerSSRC(serverId, null); | |
145 | 146 | } |
146 | 147 | cacheUtils.put(cacheName, key, serverItem); |
147 | 148 | resetOnlineServerItem(serverItem); |
... | ... | @@ -161,12 +162,19 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { |
161 | 162 | } |
162 | 163 | |
163 | 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 | 179 | @Override |
172 | 180 | public void resetOnlineServerItem(MediaServerDTO mediaServerItem) { | ... | ... |
... | ... | @@ -24,11 +24,8 @@ import org.thingsboard.server.common.data.id.EntityId; |
24 | 24 | import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; |
25 | 25 | import org.thingsboard.server.common.data.yunteng.common.media.ZlmHttpHookSubscribe; |
26 | 26 | import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; |
27 | -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; | |
28 | 27 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
29 | 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 | 29 | import org.thingsboard.server.common.data.yunteng.dto.sip.*; |
33 | 30 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherPsSendInfo; |
34 | 31 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherRtpSendInfo; |
... | ... | @@ -111,7 +108,7 @@ public class TkMediaServerServiceImpl |
111 | 108 | TkMediaServerEntity entity = |
112 | 109 | baseMapper.selectOne( |
113 | 110 | new LambdaQueryWrapper<TkMediaServerEntity>() |
114 | - .eq(TkMediaServerEntity::getTenantId, tenantId) | |
111 | + // .eq(TkMediaServerEntity::getTenantId, tenantId) | |
115 | 112 | .eq(TkMediaServerEntity::getMediaServerId, id)); |
116 | 113 | return Optional.ofNullable(entity).map(obj -> obj.getDTO(MediaServerDTO.class)).orElse(null); |
117 | 114 | } |
... | ... | @@ -126,28 +123,24 @@ public class TkMediaServerServiceImpl |
126 | 123 | } |
127 | 124 | |
128 | 125 | @Override |
129 | - public MediaServerDTO saveOrUpdateMediaServer(MediaServerDTO mediaServer) { | |
126 | + public MediaServerDTO saveMediaServer(MediaServerDTO mediaServer) { | |
130 | 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 | 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 | 144 | if (null != mediaServerDTO) { |
152 | 145 | return mediaServerDTO; |
153 | 146 | } else { |
... | ... | @@ -157,9 +150,9 @@ public class TkMediaServerServiceImpl |
157 | 150 | } |
158 | 151 | |
159 | 152 | @Override |
160 | - public MediaServerDTO getMediaServerForPlay(String tenantId, String mediaServerId) { | |
153 | + public MediaServerDTO getMediaServerForPlay(String sipId, String mediaServerId) { | |
161 | 154 | if (StringUtils.isEmpty(mediaServerId)) { |
162 | - return getMediaServerForMinimumLoad(tenantId); | |
155 | + return getMediaServerForMinimumLoad(sipId); | |
163 | 156 | } else { |
164 | 157 | return getMediaServerByMediaServerId(mediaServerId); |
165 | 158 | } |
... | ... | @@ -595,7 +588,8 @@ public class TkMediaServerServiceImpl |
595 | 588 | ret.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, playStream.getChannelId()); |
596 | 589 | ret.put(FastIotConstants.ZLMediaBody.CAMERA_CODE, playStream.getCameraCode()); |
597 | 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 | 643 | |
650 | 644 | @Override |
651 | 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 | 649 | // TODO |
655 | 650 | return HookResult.SUCCESS(); |
656 | 651 | } |
... | ... | @@ -760,22 +755,22 @@ public class TkMediaServerServiceImpl |
760 | 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 | 775 | private HookResultForOnPublish appIsNotRtp(BaseParam param, MediaServerDTO mediaInfo) { |
781 | 776 | // HookResultForOnPublish hookResultForOnPublish = new HookResultForOnPublish(401, | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service.media; |
2 | 2 | |
3 | 3 | import java.util.Optional; |
4 | - | |
5 | 4 | import org.thingsboard.server.common.data.yunteng.common.media.CommonCallback; |
6 | 5 | import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; |
7 | 6 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; |
... | ... | @@ -20,10 +19,23 @@ public interface TkMediaServerNodeService { |
20 | 19 | /** zlm 重启后重置他的推流信息 */ |
21 | 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 | 30 | void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig); |
26 | 31 | |
32 | + /** | |
33 | + * 处理zlm上线 | |
34 | + * | |
35 | + * @param mediaServerId ZLM返回的流媒体配置 | |
36 | + */ | |
37 | + void zlmServerOffline(String mediaServerId); | |
38 | + | |
27 | 39 | void resetOnlineServerItem(MediaServerDTO mediaServerItem); |
28 | 40 | |
29 | 41 | /** | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service.media; |
2 | 2 | |
3 | 3 | import com.fasterxml.jackson.databind.JsonNode; |
4 | +import java.util.List; | |
4 | 5 | import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; |
5 | 6 | import org.thingsboard.server.common.data.yunteng.dto.sip.StreamInfoDTO; |
6 | 7 | import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; |
7 | 8 | |
8 | -import java.util.List; | |
9 | - | |
10 | 9 | public interface TkMediaServerService { |
11 | 10 | |
12 | 11 | /** |
... | ... | @@ -15,6 +14,7 @@ public interface TkMediaServerService { |
15 | 14 | * @return 流媒体列表 |
16 | 15 | */ |
17 | 16 | List<MediaServerDTO> getAllMediaKit(); |
17 | + | |
18 | 18 | /** |
19 | 19 | * 通过流媒体ID获取流媒体信息 |
20 | 20 | * |
... | ... | @@ -37,7 +37,15 @@ public interface TkMediaServerService { |
37 | 37 | * @param mediaServer 流媒体信息 |
38 | 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 | 53 | * @param tenantId 租户ID |
46 | 54 | * @return 流媒体信息 |
47 | 55 | */ |
56 | + @Deprecated | |
48 | 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> | ... | ... |
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 | 119 | enabled: "${TB_JS_REMOTE_STATS_ENABLED:false}" |
120 | 120 | print_interval_ms: "${TB_JS_REMOTE_STATS_PRINT_INTERVAL_MS:10000}" |
121 | 121 | |
122 | -# GBT28181_ server parameters | |
122 | +# GBT28181 server parameters | |
123 | 123 | transport: |
124 | 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 | 165 | sessions: |
175 | 166 | inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" |
176 | 167 | report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:3000}" | ... | ... |