Commit 85b24ea06b0579dd13551fbf92a0fe243adb9792

Authored by xp.Huang
2 parents 6b070a7f 0db46d8c

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 }
... ...
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 }
... ...
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 }
... ...
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   -}
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(
... ...
  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
1   -package org.thingsboard.server.transport.gbt28181;
  1 +package org.thingsboard.server.transport.gbt28181.sip;
2 2
3 3 import lombok.extern.log4j.Log4j;
4 4
... ...
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
1   -package org.thingsboard.server.transport.gbt28181;
  1 +package org.thingsboard.server.transport.gbt28181.sip;
2 2
3 3 import javax.sip.RequestEvent;
4 4
... ...
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
1   -package org.thingsboard.server.transport.gbt28181;
  1 +package org.thingsboard.server.transport.gbt28181.sip;
2 2
3 3 import javax.sip.ResponseEvent;
4 4
... ...
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
1   -package org.thingsboard.server.transport.gbt28181;
  1 +package org.thingsboard.server.transport.gbt28181.sip.processor;
2 2
3 3 import javax.sip.TimeoutEvent;
4 4
... ...
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
1   -package org.thingsboard.server.transport;
  1 +package org.thingsboard.server.transport.gbt28181.sip.processor;
2 2
3 3 import javax.sip.SipListener;
4 4
... ...
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 +}
... ...
1   -package org.thingsboard.server.transport.process.timeout;
2   -
3   -import javax.sip.TimeoutEvent;
4   -
5   -public interface ITimeoutProcessor {
6   - void process(TimeoutEvent event);
7   -}
... ... @@ -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,
... ...
... ... @@ -60,6 +60,7 @@ public interface TkCacheStorageService {
60 60 * @param tenantId 租户ID
61 61 * @return 流媒体信息
62 62 */
  63 + @Deprecated
63 64 MediaServerDTO findMediaServerForMinimumLoad(String tenantId);
64 65
65 66 /**
... ...
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 /**
... ...
  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
... ...
  1 +<!--
  2 +
  3 + Copyright © 2016-2022 The Thingsboard Authors
  4 +
  5 + Licensed under the Apache License, Version 2.0 (the "License");
  6 + you may not use this file except in compliance with the License.
  7 + You may obtain a copy of the License at
  8 +
  9 + http://www.apache.org/licenses/LICENSE-2.0
  10 +
  11 + Unless required by applicable law or agreed to in writing, software
  12 + distributed under the License is distributed on an "AS IS" BASIS,
  13 + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14 + See the License for the specific language governing permissions and
  15 + limitations under the License.
  16 +
  17 +-->
  18 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  19 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  20 + <modelVersion>4.0.0</modelVersion>
  21 + <parent>
  22 + <groupId>org.thingsboard.msa</groupId>
  23 + <version>3.3.4-SNAPSHOT</version>
  24 + <artifactId>transport</artifactId>
  25 + </parent>
  26 + <groupId>org.thingsboard.msa.transport</groupId>
  27 + <artifactId>gbt28181</artifactId>
  28 + <packaging>pom</packaging>
  29 +
  30 + <name>ThingsBoard GBT28181 Transport Microservice</name>
  31 + <url>https://thingsboard.io</url>
  32 + <description>ThingsBoard GBT28181 Transport Microservice</description>
  33 +
  34 + <properties>
  35 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  36 + <main.dir>${basedir}/../../..</main.dir>
  37 + <pkg.name>tb-gbt28181-transport</pkg.name>
  38 + <docker.name>tb-gbt28181-transport</docker.name>
  39 + <pkg.logFolder>/var/log/${pkg.name}</pkg.logFolder>
  40 + <pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
  41 + <docker.push-arm-amd-image.phase>pre-integration-test</docker.push-arm-amd-image.phase>
  42 + </properties>
  43 +
  44 + <dependencies>
  45 + <dependency>
  46 + <groupId>org.thingsboard.transport</groupId>
  47 + <artifactId>gbt28181</artifactId>
  48 + <version>${project.version}</version>
  49 + <classifier>deb</classifier>
  50 + <type>deb</type>
  51 + <scope>provided</scope>
  52 + </dependency>
  53 + </dependencies>
  54 +
  55 + <build>
  56 + <plugins>
  57 + <plugin>
  58 + <groupId>org.apache.maven.plugins</groupId>
  59 + <artifactId>maven-dependency-plugin</artifactId>
  60 + <executions>
  61 + <execution>
  62 + <id>copy-tb-gbt28181-transport-deb</id>
  63 + <phase>package</phase>
  64 + <goals>
  65 + <goal>copy</goal>
  66 + </goals>
  67 + <configuration>
  68 + <artifactItems>
  69 + <artifactItem>
  70 + <groupId>org.thingsboard.transport</groupId>
  71 + <artifactId>gbt28181</artifactId>
  72 + <classifier>deb</classifier>
  73 + <type>deb</type>
  74 + <destFileName>${pkg.name}.deb</destFileName>
  75 + <outputDirectory>${project.build.directory}</outputDirectory>
  76 + </artifactItem>
  77 + </artifactItems>
  78 + </configuration>
  79 + </execution>
  80 + </executions>
  81 + </plugin>
  82 + <plugin>
  83 + <groupId>org.apache.maven.plugins</groupId>
  84 + <artifactId>maven-resources-plugin</artifactId>
  85 + <executions>
  86 + <execution>
  87 + <id>copy-docker-config</id>
  88 + <phase>process-resources</phase>
  89 + <goals>
  90 + <goal>copy-resources</goal>
  91 + </goals>
  92 + <configuration>
  93 + <outputDirectory>${project.build.directory}</outputDirectory>
  94 + <resources>
  95 + <resource>
  96 + <directory>docker</directory>
  97 + <filtering>true</filtering>
  98 + </resource>
  99 + </resources>
  100 + </configuration>
  101 + </execution>
  102 + </executions>
  103 + </plugin>
  104 + <plugin>
  105 + <groupId>com.spotify</groupId>
  106 + <artifactId>dockerfile-maven-plugin</artifactId>
  107 + <executions>
  108 + <execution>
  109 + <id>build-docker-image</id>
  110 + <phase>pre-integration-test</phase>
  111 + <goals>
  112 + <goal>build</goal>
  113 + </goals>
  114 + <configuration>
  115 + <skip>${dockerfile.skip}</skip>
  116 + <repository>${docker.repo}/${docker.name}</repository>
  117 + <verbose>true</verbose>
  118 + <googleContainerRegistryEnabled>false</googleContainerRegistryEnabled>
  119 + <contextDirectory>${project.build.directory}</contextDirectory>
  120 + </configuration>
  121 + </execution>
  122 + <execution>
  123 + <id>tag-docker-image</id>
  124 + <phase>pre-integration-test</phase>
  125 + <goals>
  126 + <goal>tag</goal>
  127 + </goals>
  128 + <configuration>
  129 + <skip>${dockerfile.skip}</skip>
  130 + <repository>${docker.repo}/${docker.name}</repository>
  131 + <tag>${project.version}</tag>
  132 + </configuration>
  133 + </execution>
  134 + </executions>
  135 + </plugin>
  136 + </plugins>
  137 + </build>
  138 + <profiles>
  139 + <profile>
  140 + <id>push-docker-image</id>
  141 + <activation>
  142 + <property>
  143 + <name>push-docker-image</name>
  144 + </property>
  145 + </activation>
  146 + <build>
  147 + <plugins>
  148 + <plugin>
  149 + <groupId>com.spotify</groupId>
  150 + <artifactId>dockerfile-maven-plugin</artifactId>
  151 + <executions>
  152 + <execution>
  153 + <id>push-latest-docker-image</id>
  154 + <phase>pre-integration-test</phase>
  155 + <goals>
  156 + <goal>push</goal>
  157 + </goals>
  158 + <configuration>
  159 + <tag>latest</tag>
  160 + <repository>${docker.repo}/${docker.name}</repository>
  161 + </configuration>
  162 + </execution>
  163 + <execution>
  164 + <id>push-version-docker-image</id>
  165 + <phase>pre-integration-test</phase>
  166 + <goals>
  167 + <goal>push</goal>
  168 + </goals>
  169 + <configuration>
  170 + <tag>${project.version}</tag>
  171 + <repository>${docker.repo}/${docker.name}</repository>
  172 + </configuration>
  173 + </execution>
  174 + </executions>
  175 + </plugin>
  176 + </plugins>
  177 + </build>
  178 + </profile>
  179 + </profiles>
  180 + <repositories>
  181 + <repository>
  182 + <id>jenkins</id>
  183 + <name>Jenkins Repository</name>
  184 + <url>https://repo.jenkins-ci.org/releases</url>
  185 + <snapshots>
  186 + <enabled>false</enabled>
  187 + </snapshots>
  188 + </repository>
  189 + </repositories>
  190 +</project>
... ...
... ... @@ -40,5 +40,7 @@
40 40 <module>coap</module>
41 41 <module>lwm2m</module>
42 42 <module>snmp</module>
  43 + <module>tcp</module>
  44 + <module>gbt28181</module>
43 45 </modules>
44 46 </project>
... ...
  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
... ...
  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}"
... ...