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,7 +36,6 @@ public class TkVideoControlController extends BaseController {
36 36
37 @GetMapping("/start/{deviceId}/{channelId}") 37 @GetMapping("/start/{deviceId}/{channelId}")
38 @ApiOperation(value = "视频点播/预览") 38 @ApiOperation(value = "视频点播/预览")
39 -// @PreAuthorize("@check.checkPermissions({'SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:video:control:play'})")  
40 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER')") 39 @PreAuthorize("hasAnyAuthority('SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER')")
41 public DeferredResult<ResponseResult<StreamContentDTO>> startPlay( 40 public DeferredResult<ResponseResult<StreamContentDTO>> startPlay(
42 @PathVariable("deviceId") String tbDeviceId, @PathVariable("channelId") String channelId) 41 @PathVariable("deviceId") String tbDeviceId, @PathVariable("channelId") String channelId)
@@ -3,16 +3,17 @@ package org.thingsboard.server.controller.yunteng.media; @@ -3,16 +3,17 @@ package org.thingsboard.server.controller.yunteng.media;
3 import com.fasterxml.jackson.databind.JsonNode; 3 import com.fasterxml.jackson.databind.JsonNode;
4 import io.swagger.annotations.Api; 4 import io.swagger.annotations.Api;
5 import io.swagger.annotations.ApiOperation; 5 import io.swagger.annotations.ApiOperation;
  6 +import javax.servlet.http.HttpServletRequest;
6 import lombok.RequiredArgsConstructor; 7 import lombok.RequiredArgsConstructor;
7 import lombok.extern.slf4j.Slf4j; 8 import lombok.extern.slf4j.Slf4j;
  9 +import org.json.JSONObject;
8 import org.springframework.web.bind.annotation.*; 10 import org.springframework.web.bind.annotation.*;
  11 +import org.springframework.web.context.request.async.DeferredResult;
9 import org.thingsboard.server.common.data.exception.ThingsboardException; 12 import org.thingsboard.server.common.data.exception.ThingsboardException;
10 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 13 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
11 -import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO;  
12 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; 14 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO;
13 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; 15 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*;
14 import org.thingsboard.server.controller.BaseController; 16 import org.thingsboard.server.controller.BaseController;
15 -import org.thingsboard.server.dao.yunteng.service.TkDeviceService;  
16 import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService; 17 import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService;
17 import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; 18 import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService;
18 import org.thingsboard.server.service.yunteng.media.TkVideoControlService; 19 import org.thingsboard.server.service.yunteng.media.TkVideoControlService;
@@ -57,21 +58,140 @@ public class ZLMediaKitHookController extends BaseController { @@ -57,21 +58,140 @@ public class ZLMediaKitHookController extends BaseController {
57 @ResponseBody 58 @ResponseBody
58 @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8") 59 @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8")
59 @ApiOperation(value = "流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流") 60 @ApiOperation(value = "流无人观看时事件,用户可以通过此事件选择是否关闭无人看的流")
60 - public JsonNode onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) throws ThingsboardException { 61 + public JsonNode onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param)
  62 + throws ThingsboardException {
61 JsonNode result = tkMediaServerService.zlmOnStreamNoneReader(param); 63 JsonNode result = tkMediaServerService.zlmOnStreamNoneReader(param);
62 - if(result.has(FastIotConstants.ZLMediaBody.CHANNEL_ID) &&result.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)){ 64 + if (result.has(FastIotConstants.ZLMediaBody.CHANNEL_ID)
  65 + && result.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)) {
63 String channelId = result.get(FastIotConstants.ZLMediaBody.CHANNEL_ID).asText(); 66 String channelId = result.get(FastIotConstants.ZLMediaBody.CHANNEL_ID).asText();
64 String cameraCode = result.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText(); 67 String cameraCode = result.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText();
65 - VideoChanelDTO chanelDTO = tkVideoChannelService.findVideoChannelById(cameraCode,channelId, null);  
66 - controlService.byeCmdInSsrcTransaction(chanelDTO.getTenantId(),  
67 - false,  
68 - chanelDTO.getDeviceId(),  
69 - cameraCode,channelId,result.get(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM).asText(),  
70 - fromDeviceRpcResponse->{  
71 -  
72 - });  
73 - tkVideoChannelService.updateVideoChannelStreamId(null, cameraCode, channelId);//storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 68 + VideoChanelDTO chanelDTO =
  69 + tkVideoChannelService.findVideoChannelById(cameraCode, channelId, null);
  70 + controlService.byeCmdInSsrcTransaction(
  71 + chanelDTO.getTenantId(),
  72 + false,
  73 + chanelDTO.getDeviceId(),
  74 + cameraCode,
  75 + channelId,
  76 + result.get(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM).asText(),
  77 + fromDeviceRpcResponse -> {});
  78 + tkVideoChannelService.updateVideoChannelStreamId(
  79 + null,
  80 + cameraCode,
  81 + channelId); // storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
74 } 82 }
75 return result; 83 return result;
76 } 84 }
  85 +
  86 + /** 流未找到事件,用户可以在此事件触发时,立即去拉流,这样可以实现按需拉流;此事件对回复不敏感。 */
  87 + @ResponseBody
  88 + @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8")
  89 + public DeferredResult<HookResult> onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param) {
  90 + // log.error("WEBHOOK流未找到【on_stream_not_found】,API参数【{}】",JSONObject.toJSONString(param));
  91 +
  92 + DeferredResult<HookResult> defaultResult = new DeferredResult<>();
  93 +
  94 + // MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId());
  95 + // if (!userSetting.isAutoApplyPlay() || mediaInfo == null) {
  96 + // defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(),
  97 + // ErrorCode.ERROR404.getMsg()));
  98 + // return defaultResult;
  99 + // }
  100 + //
  101 + // if ("rtp".equals(param.getApp())) {
  102 + // String[] s = param.getStream().split("_");
  103 + // if (!mediaInfo.isRtpEnable() || s.length != 2) {
  104 + // defaultResult.setResult(HookResult.SUCCESS());
  105 + // return defaultResult;
  106 + // }
  107 + // String deviceId = s[0];
  108 + // String channelId = s[1];
  109 + // Device device = redisCatchStorage.getDevice(deviceId);
  110 + // if (device == null) {
  111 + // defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(),
  112 + // ErrorCode.ERROR404.getMsg()));
  113 + // return defaultResult;
  114 + // }
  115 + // DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
  116 + // if (deviceChannel == null) {
  117 + // defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(),
  118 + // ErrorCode.ERROR404.getMsg()));
  119 + // return defaultResult;
  120 + // }
  121 + // logger.info("[ZLM HOOK] 流未找到, 发起自动点播:{}->{}->{}/{}", param.getMediaServerId(),
  122 + // param.getSchema(), param.getApp(), param.getStream());
  123 + // RequestMessage msg = new RequestMessage();
  124 + // String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
  125 + // boolean exist = resultHolder.exist(key, null);
  126 + // msg.setKey(key);
  127 + // String uuid = UUID.randomUUID().toString();
  128 + // msg.setId(uuid);
  129 + // DeferredResult<HookResult> result = new
  130 + // DeferredResult<>(userSetting.getPlayTimeout().longValue());
  131 + // DeferredResultEx<HookResult> deferredResultEx = new DeferredResultEx<>(result);
  132 + //
  133 + // result.onTimeout(() -> {
  134 + // logger.info("点播接口等待超时");
  135 + // // 释放rtpserver
  136 + // msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时"));
  137 + // resultHolder.invokeResult(msg);
  138 + // });
  139 + // // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误
  140 + // deferredResultEx.setFilter(result1 -> {
  141 + // WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>) result1;
  142 + // HookResult resultForEnd = new HookResult();
  143 + // resultForEnd.setCode(wvpResult1.getCode());
  144 + // resultForEnd.setMsg(wvpResult1.getMsg());
  145 + // return resultForEnd;
  146 + // });
  147 + //
  148 + // // 录像查询以channelId作为deviceId查询
  149 + // resultHolder.put(key, uuid, deferredResultEx);
  150 + //
  151 + // if (!exist) {
  152 + // playService.play(mediaInfo, deviceId, channelId, null, eventResult -> {
  153 + // msg.setData(new HookResult(eventResult.statusCode, eventResult.msg));
  154 + // resultHolder.invokeResult(msg);
  155 + // }, null);
  156 + // }
  157 + // return result;
  158 + // } else {
  159 + // // 拉流代理
  160 + // StreamProxyItem streamProxyByAppAndStream =
  161 + // streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream());
  162 + // if (streamProxyByAppAndStream != null &&
  163 + // streamProxyByAppAndStream.isEnable_disable_none_reader()) {
  164 + // streamProxyService.start(param.getApp(), param.getStream());
  165 + // }
  166 + // DeferredResult<HookResult> result = new DeferredResult<>();
  167 + // result.setResult(HookResult.SUCCESS());
  168 + // return result;
  169 + // }
  170 + return defaultResult;
  171 + }
  172 +
  173 + /** 服务器启动事件,可以用于监听服务器崩溃重启;此事件对回复不敏感。 */
  174 + @ResponseBody
  175 + @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8")
  176 + public HookResult onServerStarted(
  177 + HttpServletRequest request, @RequestBody JSONObject jsonObject) {
  178 + //
  179 + // log.error("WEBHOOK服务器已启动【on_server_started】,请求对象【{}】,API参数【{}】",JSONObject.toJSONString(request),jsonObject);
  180 + // jsonObject.put("ip", request.getRemoteAddr());
  181 + // ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject);
  182 + // zlmServerConfig.setIp(request.getRemoteAddr());
  183 + // logger.info("[ZLM HOOK] zlm 启动 " + zlmServerConfig.getGeneralMediaServerId());
  184 + // taskExecutor.execute(() -> {
  185 + // List<ZlmHttpHookSubscribe.Event> subscribes =
  186 + // this.subscribe.getSubscribes(HookType.on_server_started);
  187 + // if (subscribes != null && subscribes.size() > 0) {
  188 + // for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
  189 + // subscribe.response(null, jsonObject);
  190 + // }
  191 + // }
  192 + // mediaServerService.zlmServerOnline(zlmServerConfig);
  193 + // });
  194 +
  195 + return HookResult.SUCCESS();
  196 + }
77 } 197 }
1 /** 1 /**
2 * Copyright © 2016-2022 The Thingsboard Authors 2 * Copyright © 2016-2022 The Thingsboard Authors
3 * 3 *
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at 4 + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5 + * except in compliance with the License. You may obtain a copy of the License at
7 * 6 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 7 + * <p>http://www.apache.org/licenses/LICENSE-2.0
9 * 8 *
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and 9 + * <p>Unless required by applicable law or agreed to in writing, software distributed under the
  10 + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  11 + * express or implied. See the License for the specific language governing permissions and
14 * limitations under the License. 12 * limitations under the License.
15 */ 13 */
16 package org.thingsboard.server.service.transport; 14 package org.thingsboard.server.service.transport;
@@ -37,7 +35,6 @@ import java.util.concurrent.locks.ReentrantLock; @@ -37,7 +35,6 @@ import java.util.concurrent.locks.ReentrantLock;
37 import java.util.stream.Collectors; 35 import java.util.stream.Collectors;
38 import lombok.RequiredArgsConstructor; 36 import lombok.RequiredArgsConstructor;
39 import lombok.extern.slf4j.Slf4j; 37 import lombok.extern.slf4j.Slf4j;
40 -import org.apache.zookeeper.Op;  
41 import org.springframework.stereotype.Service; 38 import org.springframework.stereotype.Service;
42 import org.thingsboard.common.util.JacksonUtil; 39 import org.thingsboard.common.util.JacksonUtil;
43 import org.thingsboard.server.cache.ota.OtaPackageDataCache; 40 import org.thingsboard.server.cache.ota.OtaPackageDataCache;
@@ -74,13 +71,15 @@ import org.thingsboard.server.common.data.relation.EntityRelation; @@ -74,13 +71,15 @@ import org.thingsboard.server.common.data.relation.EntityRelation;
74 import org.thingsboard.server.common.data.security.DeviceCredentials; 71 import org.thingsboard.server.common.data.security.DeviceCredentials;
75 import org.thingsboard.server.common.data.security.DeviceCredentialsType; 72 import org.thingsboard.server.common.data.security.DeviceCredentialsType;
76 import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; 73 import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager;
  74 +import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig;
77 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 75 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
78 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; 76 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO;
79 import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO; 77 import org.thingsboard.server.common.data.yunteng.dto.TkDeviceScriptDTO;
  78 +import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO;
80 import org.thingsboard.server.common.data.yunteng.dto.sip.SipDeviceDTO; 79 import org.thingsboard.server.common.data.yunteng.dto.sip.SipDeviceDTO;
81 -import org.thingsboard.server.common.data.yunteng.dto.sip.SsrcTransactionDTO;  
82 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; 80 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO;
83 import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum; 81 import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum;
  82 +import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils;
84 import org.thingsboard.server.common.msg.EncryptionUtil; 83 import org.thingsboard.server.common.msg.EncryptionUtil;
85 import org.thingsboard.server.common.msg.TbMsg; 84 import org.thingsboard.server.common.msg.TbMsg;
86 import org.thingsboard.server.common.msg.TbMsgDataType; 85 import org.thingsboard.server.common.msg.TbMsgDataType;
@@ -99,6 +98,7 @@ import org.thingsboard.server.dao.yunteng.entities.TkVideoChannelEntity; @@ -99,6 +98,7 @@ import org.thingsboard.server.dao.yunteng.entities.TkVideoChannelEntity;
99 import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService; 98 import org.thingsboard.server.dao.yunteng.service.TkDeviceScriptService;
100 import org.thingsboard.server.dao.yunteng.service.TkDeviceService; 99 import org.thingsboard.server.dao.yunteng.service.TkDeviceService;
101 import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerNodeService; 100 import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerNodeService;
  101 +import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService;
102 import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService; 102 import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService;
103 import org.thingsboard.server.gen.transport.TransportProtos; 103 import org.thingsboard.server.gen.transport.TransportProtos;
104 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; 104 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
@@ -126,650 +126,891 @@ import org.thingsboard.server.service.install.DefaultSystemDataLoaderService; @@ -126,650 +126,891 @@ import org.thingsboard.server.service.install.DefaultSystemDataLoaderService;
126 import org.thingsboard.server.service.profile.TbDeviceProfileCache; 126 import org.thingsboard.server.service.profile.TbDeviceProfileCache;
127 import org.thingsboard.server.service.resource.TbResourceService; 127 import org.thingsboard.server.service.resource.TbResourceService;
128 128
129 -/**  
130 - * Created by ashvayka on 05.10.18.  
131 - */ 129 +/** Created by ashvayka on 05.10.18. */
132 @Slf4j 130 @Slf4j
133 @Service 131 @Service
134 @TbCoreComponent 132 @TbCoreComponent
135 @RequiredArgsConstructor 133 @RequiredArgsConstructor
136 public class DefaultTransportApiService implements TransportApiService { 134 public class DefaultTransportApiService implements TransportApiService {
137 135
138 - private static final ObjectMapper mapper = new ObjectMapper();  
139 -  
140 - private final TbDeviceProfileCache deviceProfileCache;  
141 - private final TbTenantProfileCache tenantProfileCache;  
142 - private final TbApiUsageStateService apiUsageStateService;  
143 - private final DeviceService deviceService;  
144 - private final TkDeviceService ytDeviceService;  
145 - private final TkDeviceScriptService scriptService;  
146 - private final TkVideoChannelService channelService;  
147 - private final TkMediaServerNodeService mediaServerNodeService;  
148 - private final VideoStreamSessionManager videoStreamSessionManager;  
149 -  
150 - private final RelationService relationService;  
151 - private final DeviceCredentialsService deviceCredentialsService;  
152 - private final DbCallbackExecutorService dbCallbackExecutorService;  
153 - private final TbClusterService tbClusterService;  
154 - private final DataDecodingEncodingService dataDecodingEncodingService;  
155 - private final DeviceProvisionService deviceProvisionService;  
156 - private final TbResourceService resourceService;  
157 - private final OtaPackageService otaPackageService;  
158 - private final OtaPackageDataCache otaPackageDataCache;  
159 -  
160 - private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks = new ConcurrentHashMap<>();  
161 -  
162 - private static boolean checkIsMqttCredentials(DeviceCredentials credentials) {  
163 - return credentials != null && DeviceCredentialsType.MQTT_BASIC.equals(credentials.getCredentialsType()); 136 + private static final ObjectMapper mapper = new ObjectMapper();
  137 +
  138 + private final TbDeviceProfileCache deviceProfileCache;
  139 + private final TbTenantProfileCache tenantProfileCache;
  140 + private final TbApiUsageStateService apiUsageStateService;
  141 + private final DeviceService deviceService;
  142 + private final TkDeviceService ytDeviceService;
  143 + private final TkDeviceScriptService scriptService;
  144 + private final TkVideoChannelService channelService;
  145 + private final TkMediaServerNodeService mediaServerNodeService;
  146 + private final VideoStreamSessionManager videoStreamSessionManager;
  147 + private final TkMediaServerService mediaServerService;
  148 + private final ZLMediaKitRestFulUtils zlMediaKitRestFulUtils;
  149 +
  150 + private final RelationService relationService;
  151 + private final DeviceCredentialsService deviceCredentialsService;
  152 + private final DbCallbackExecutorService dbCallbackExecutorService;
  153 + private final TbClusterService tbClusterService;
  154 + private final DataDecodingEncodingService dataDecodingEncodingService;
  155 + private final DeviceProvisionService deviceProvisionService;
  156 + private final TbResourceService resourceService;
  157 + private final OtaPackageService otaPackageService;
  158 + private final OtaPackageDataCache otaPackageDataCache;
  159 +
  160 + private final ConcurrentMap<String, ReentrantLock> deviceCreationLocks =
  161 + new ConcurrentHashMap<>();
  162 +
  163 + private static boolean checkIsMqttCredentials(DeviceCredentials credentials) {
  164 + return credentials != null
  165 + && DeviceCredentialsType.MQTT_BASIC.equals(credentials.getCredentialsType());
  166 + }
  167 +
  168 + @Override
  169 + public ListenableFuture<TbProtoQueueMsg<TransportApiResponseMsg>> handle(
  170 + TbProtoQueueMsg<TransportApiRequestMsg> tbProtoQueueMsg) {
  171 + TransportApiRequestMsg transportApiRequestMsg = tbProtoQueueMsg.getValue();
  172 + ListenableFuture<TransportApiResponseMsg> result = null;
  173 +
  174 + if (transportApiRequestMsg.hasValidateTokenRequestMsg()) {
  175 + ValidateDeviceTokenRequestMsg msg = transportApiRequestMsg.getValidateTokenRequestMsg();
  176 + result = validateCredentials(msg.getToken(), DeviceCredentialsType.ACCESS_TOKEN);
  177 + } else if (transportApiRequestMsg.hasValidateBasicMqttCredRequestMsg()) {
  178 + TransportProtos.ValidateBasicMqttCredRequestMsg msg =
  179 + transportApiRequestMsg.getValidateBasicMqttCredRequestMsg();
  180 + result = validateCredentials(msg);
  181 + } else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) {
  182 + ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg();
  183 + result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE);
  184 + } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) {
  185 + result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg());
  186 + } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) {
  187 + result = handle(transportApiRequestMsg.getEntityProfileRequestMsg());
  188 + } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) {
  189 + result = handle(transportApiRequestMsg.getLwM2MRequestMsg());
  190 + } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) {
  191 + ValidateDeviceLwM2MCredentialsRequestMsg msg =
  192 + transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg();
  193 + result = validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS);
  194 + } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) {
  195 + result = handle(transportApiRequestMsg.getProvisionDeviceRequestMsg());
  196 + } else if (transportApiRequestMsg.hasResourceRequestMsg()) {
  197 + result = handle(transportApiRequestMsg.getResourceRequestMsg());
  198 + } else if (transportApiRequestMsg.hasSnmpDevicesRequestMsg()) {
  199 + result = handle(transportApiRequestMsg.getSnmpDevicesRequestMsg());
  200 + } else if (transportApiRequestMsg.hasDeviceRequestMsg()) {
  201 + result = handle(transportApiRequestMsg.getDeviceRequestMsg());
  202 + } else if (transportApiRequestMsg.hasDeviceCredentialsRequestMsg()) {
  203 + result = handle(transportApiRequestMsg.getDeviceCredentialsRequestMsg());
  204 + } else if (transportApiRequestMsg.hasOtaPackageRequestMsg()) {
  205 + result = handle(transportApiRequestMsg.getOtaPackageRequestMsg());
164 } 206 }
165 207
166 - @Override  
167 - public ListenableFuture<TbProtoQueueMsg<TransportApiResponseMsg>> handle(TbProtoQueueMsg<TransportApiRequestMsg> tbProtoQueueMsg) {  
168 - TransportApiRequestMsg transportApiRequestMsg = tbProtoQueueMsg.getValue();  
169 - ListenableFuture<TransportApiResponseMsg> result = null;  
170 -  
171 - if (transportApiRequestMsg.hasValidateTokenRequestMsg()) {  
172 - ValidateDeviceTokenRequestMsg msg = transportApiRequestMsg.getValidateTokenRequestMsg();  
173 - result = validateCredentials(msg.getToken(), DeviceCredentialsType.ACCESS_TOKEN);  
174 - } else if (transportApiRequestMsg.hasValidateBasicMqttCredRequestMsg()) {  
175 - TransportProtos.ValidateBasicMqttCredRequestMsg msg = transportApiRequestMsg.getValidateBasicMqttCredRequestMsg();  
176 - result = validateCredentials(msg);  
177 - } else if (transportApiRequestMsg.hasValidateX509CertRequestMsg()) {  
178 - ValidateDeviceX509CertRequestMsg msg = transportApiRequestMsg.getValidateX509CertRequestMsg();  
179 - result = validateCredentials(msg.getHash(), DeviceCredentialsType.X509_CERTIFICATE);  
180 - } else if (transportApiRequestMsg.hasGetOrCreateDeviceRequestMsg()) {  
181 - result = handle(transportApiRequestMsg.getGetOrCreateDeviceRequestMsg());  
182 - } else if (transportApiRequestMsg.hasEntityProfileRequestMsg()) {  
183 - result = handle(transportApiRequestMsg.getEntityProfileRequestMsg());  
184 - } else if (transportApiRequestMsg.hasLwM2MRequestMsg()) {  
185 - result = handle(transportApiRequestMsg.getLwM2MRequestMsg());  
186 - } else if (transportApiRequestMsg.hasValidateDeviceLwM2MCredentialsRequestMsg()) {  
187 - ValidateDeviceLwM2MCredentialsRequestMsg msg = transportApiRequestMsg.getValidateDeviceLwM2MCredentialsRequestMsg();  
188 - result = validateCredentials(msg.getCredentialsId(), DeviceCredentialsType.LWM2M_CREDENTIALS);  
189 - } else if (transportApiRequestMsg.hasProvisionDeviceRequestMsg()) {  
190 - result = handle(transportApiRequestMsg.getProvisionDeviceRequestMsg());  
191 - } else if (transportApiRequestMsg.hasResourceRequestMsg()) {  
192 - result = handle(transportApiRequestMsg.getResourceRequestMsg());  
193 - } else if (transportApiRequestMsg.hasSnmpDevicesRequestMsg()) {  
194 - result = handle(transportApiRequestMsg.getSnmpDevicesRequestMsg());  
195 - } else if (transportApiRequestMsg.hasDeviceRequestMsg()) {  
196 - result = handle(transportApiRequestMsg.getDeviceRequestMsg());  
197 - } else if (transportApiRequestMsg.hasDeviceCredentialsRequestMsg()) {  
198 - result = handle(transportApiRequestMsg.getDeviceCredentialsRequestMsg());  
199 - } else if (transportApiRequestMsg.hasOtaPackageRequestMsg()) {  
200 - result = handle(transportApiRequestMsg.getOtaPackageRequestMsg());  
201 - }  
202 -  
203 - //Thingskit function  
204 - else if (transportApiRequestMsg.hasScript()) {  
205 - result = handle(transportApiRequestMsg.getScript());  
206 - }  
207 - else if (transportApiRequestMsg.hasGbt28181RequestMsg()) {  
208 - result = handleGbt(transportApiRequestMsg.getGbt28181RequestMsg());  
209 - }  
210 -  
211 -  
212 - return Futures.transform(Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture),  
213 - value -> new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()),  
214 - MoreExecutors.directExecutor()); 208 + // Thingskit function
  209 + else if (transportApiRequestMsg.hasScript()) {
  210 + result = handle(transportApiRequestMsg.getScript());
  211 + } else if (transportApiRequestMsg.hasGbt28181RequestMsg()) {
  212 + result = handleGbt(transportApiRequestMsg.getGbt28181RequestMsg());
  213 + } else if (transportApiRequestMsg.hasGbt28181MediaServerMsg()) {
  214 + result = handleGbtMedia(transportApiRequestMsg.getGbt28181MediaServerMsg());
215 } 215 }
216 216
217 - private ListenableFuture<TransportApiResponseMsg> validateCredentials(String credentialsId, DeviceCredentialsType credentialsType) {  
218 - //TODO: Make async and enable caching  
219 - DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(credentialsId);  
220 - if (credentials != null && credentials.getCredentialsType() == credentialsType) {  
221 - return getDeviceInfo(credentials);  
222 - } else {  
223 - return getEmptyTransportApiResponseFuture();  
224 - } 217 + return Futures.transform(
  218 + Optional.ofNullable(result).orElseGet(this::getEmptyTransportApiResponseFuture),
  219 + value ->
  220 + new TbProtoQueueMsg<>(tbProtoQueueMsg.getKey(), value, tbProtoQueueMsg.getHeaders()),
  221 + MoreExecutors.directExecutor());
  222 + }
  223 +
  224 + private ListenableFuture<TransportApiResponseMsg> validateCredentials(
  225 + String credentialsId, DeviceCredentialsType credentialsType) {
  226 + // TODO: Make async and enable caching
  227 + DeviceCredentials credentials =
  228 + deviceCredentialsService.findDeviceCredentialsByCredentialsId(credentialsId);
  229 + if (credentials != null && credentials.getCredentialsType() == credentialsType) {
  230 + return getDeviceInfo(credentials);
  231 + } else {
  232 + return getEmptyTransportApiResponseFuture();
225 } 233 }
226 -  
227 - private ListenableFuture<TransportApiResponseMsg> validateCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) {  
228 - DeviceCredentials credentials;  
229 - if (StringUtils.isEmpty(mqtt.getUserName())) {  
230 - credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash(mqtt.getClientId()));  
231 - if (credentials != null) {  
232 - return getDeviceInfo(credentials);  
233 - } else {  
234 - return getEmptyTransportApiResponseFuture();  
235 - } 234 + }
  235 +
  236 + private ListenableFuture<TransportApiResponseMsg> validateCredentials(
  237 + TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) {
  238 + DeviceCredentials credentials;
  239 + if (StringUtils.isEmpty(mqtt.getUserName())) {
  240 + credentials = checkMqttCredentials(mqtt, EncryptionUtil.getSha3Hash(mqtt.getClientId()));
  241 + if (credentials != null) {
  242 + return getDeviceInfo(credentials);
  243 + } else {
  244 + return getEmptyTransportApiResponseFuture();
  245 + }
  246 + } else {
  247 + credentials =
  248 + deviceCredentialsService.findDeviceCredentialsByCredentialsId(
  249 + EncryptionUtil.getSha3Hash("|", mqtt.getClientId(), mqtt.getUserName()));
  250 + if (checkIsMqttCredentials(credentials)) {
  251 + var validationResult = validateMqttCredentials(mqtt, credentials);
  252 + if (VALID.equals(validationResult)) {
  253 + return getDeviceInfo(credentials);
  254 + } else if (PASSWORD_MISMATCH.equals(validationResult)) {
  255 + return getEmptyTransportApiResponseFuture();
236 } else { 256 } else {
237 - credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(  
238 - EncryptionUtil.getSha3Hash("|", mqtt.getClientId(), mqtt.getUserName()));  
239 - if (checkIsMqttCredentials(credentials)) {  
240 - var validationResult = validateMqttCredentials(mqtt, credentials);  
241 - if (VALID.equals(validationResult)) {  
242 - return getDeviceInfo(credentials);  
243 - } else if (PASSWORD_MISMATCH.equals(validationResult)) {  
244 - return getEmptyTransportApiResponseFuture();  
245 - } else {  
246 - return validateUserNameCredentials(mqtt);  
247 - }  
248 - } else {  
249 - return validateUserNameCredentials(mqtt);  
250 - } 257 + return validateUserNameCredentials(mqtt);
251 } 258 }
  259 + } else {
  260 + return validateUserNameCredentials(mqtt);
  261 + }
252 } 262 }
253 -  
254 - private ListenableFuture<TransportApiResponseMsg> validateUserNameCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) {  
255 - DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName());  
256 - if (credentials != null) {  
257 - switch (credentials.getCredentialsType()) {  
258 - case ACCESS_TOKEN:  
259 - return getDeviceInfo(credentials);  
260 - case MQTT_BASIC:  
261 - if (VALID.equals(validateMqttCredentials(mqtt, credentials))) {  
262 - return getDeviceInfo(credentials);  
263 - } else {  
264 - return getEmptyTransportApiResponseFuture();  
265 - }  
266 - }  
267 - }  
268 - return getEmptyTransportApiResponseFuture(); 263 + }
  264 +
  265 + private ListenableFuture<TransportApiResponseMsg> validateUserNameCredentials(
  266 + TransportProtos.ValidateBasicMqttCredRequestMsg mqtt) {
  267 + DeviceCredentials credentials =
  268 + deviceCredentialsService.findDeviceCredentialsByCredentialsId(mqtt.getUserName());
  269 + if (credentials != null) {
  270 + switch (credentials.getCredentialsType()) {
  271 + case ACCESS_TOKEN:
  272 + return getDeviceInfo(credentials);
  273 + case MQTT_BASIC:
  274 + if (VALID.equals(validateMqttCredentials(mqtt, credentials))) {
  275 + return getDeviceInfo(credentials);
  276 + } else {
  277 + return getEmptyTransportApiResponseFuture();
  278 + }
  279 + }
269 } 280 }
270 -  
271 - private DeviceCredentials checkMqttCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, String credId) {  
272 - return checkMqttCredentials(clientCred, deviceCredentialsService.findDeviceCredentialsByCredentialsId(credId)); 281 + return getEmptyTransportApiResponseFuture();
  282 + }
  283 +
  284 + private DeviceCredentials checkMqttCredentials(
  285 + TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, String credId) {
  286 + return checkMqttCredentials(
  287 + clientCred, deviceCredentialsService.findDeviceCredentialsByCredentialsId(credId));
  288 + }
  289 +
  290 + private DeviceCredentials checkMqttCredentials(
  291 + TransportProtos.ValidateBasicMqttCredRequestMsg clientCred,
  292 + DeviceCredentials deviceCredentials) {
  293 + if (deviceCredentials != null
  294 + && deviceCredentials.getCredentialsType() == DeviceCredentialsType.MQTT_BASIC) {
  295 + if (VALID.equals(validateMqttCredentials(clientCred, deviceCredentials))) {
  296 + return deviceCredentials;
  297 + }
273 } 298 }
274 -  
275 - private DeviceCredentials checkMqttCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, DeviceCredentials deviceCredentials) {  
276 - if (deviceCredentials != null && deviceCredentials.getCredentialsType() == DeviceCredentialsType.MQTT_BASIC) {  
277 - if (VALID.equals(validateMqttCredentials(clientCred, deviceCredentials))) {  
278 - return deviceCredentials;  
279 - }  
280 - }  
281 - return null; 299 + return null;
  300 + }
  301 +
  302 + private BasicCredentialsValidationResult validateMqttCredentials(
  303 + TransportProtos.ValidateBasicMqttCredRequestMsg clientCred,
  304 + DeviceCredentials deviceCredentials) {
  305 + BasicMqttCredentials dbCred =
  306 + JacksonUtil.fromString(deviceCredentials.getCredentialsValue(), BasicMqttCredentials.class);
  307 + if (!StringUtils.isEmpty(dbCred.getClientId())
  308 + && !dbCred.getClientId().equals(clientCred.getClientId())) {
  309 + return BasicCredentialsValidationResult.HASH_MISMATCH;
282 } 310 }
283 -  
284 - private BasicCredentialsValidationResult validateMqttCredentials(TransportProtos.ValidateBasicMqttCredRequestMsg clientCred, DeviceCredentials deviceCredentials) {  
285 - BasicMqttCredentials dbCred = JacksonUtil.fromString(deviceCredentials.getCredentialsValue(), BasicMqttCredentials.class);  
286 - if (!StringUtils.isEmpty(dbCred.getClientId()) && !dbCred.getClientId().equals(clientCred.getClientId())) {  
287 - return BasicCredentialsValidationResult.HASH_MISMATCH;  
288 - }  
289 - if (!StringUtils.isEmpty(dbCred.getUserName()) && !dbCred.getUserName().equals(clientCred.getUserName())) {  
290 - return BasicCredentialsValidationResult.HASH_MISMATCH;  
291 - }  
292 - if (!StringUtils.isEmpty(dbCred.getPassword())) {  
293 - if (StringUtils.isEmpty(clientCred.getPassword())) {  
294 - return BasicCredentialsValidationResult.PASSWORD_MISMATCH;  
295 - } else {  
296 - return dbCred.getPassword().equals(clientCred.getPassword()) ? VALID : BasicCredentialsValidationResult.PASSWORD_MISMATCH;  
297 - }  
298 - }  
299 - return VALID; 311 + if (!StringUtils.isEmpty(dbCred.getUserName())
  312 + && !dbCred.getUserName().equals(clientCred.getUserName())) {
  313 + return BasicCredentialsValidationResult.HASH_MISMATCH;
300 } 314 }
301 -  
302 - private ListenableFuture<TransportApiResponseMsg> handle(GetOrCreateDeviceFromGatewayRequestMsg requestMsg) {  
303 - DeviceId gatewayId = new DeviceId(new UUID(requestMsg.getGatewayIdMSB(), requestMsg.getGatewayIdLSB()));  
304 - ListenableFuture<Device> gatewayFuture = deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, gatewayId);  
305 - return Futures.transform(gatewayFuture, gateway -> {  
306 - Lock deviceCreationLock = deviceCreationLocks.computeIfAbsent(requestMsg.getDeviceName(), id -> new ReentrantLock());  
307 - deviceCreationLock.lock();  
308 - try {  
309 -  
310 - //Thingskit function  
311 - String slaveName = requestMsg.getDeviceName();  
312 - if(gateway.getDeviceData().getTransportConfiguration().getType() == DeviceTransportType.TCP) {  
313 - DeviceDTO iotDev = ytDeviceService.findSlaveDevice(gateway.getTenantId().getId().toString()  
314 - , gateway.getId().getId().toString()  
315 - ,slaveName);  
316 - if(iotDev == null ){  
317 - GetOrCreateDeviceFromGatewayResponseMsg.Builder builder = GetOrCreateDeviceFromGatewayResponseMsg.newBuilder();  
318 - return TransportApiResponseMsg.newBuilder()  
319 - .setGetOrCreateDeviceResponseMsg(builder.build())  
320 - .build();  
321 - }  
322 - slaveName = iotDev.getName();  
323 - }  
324 -  
325 - Device device = deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), slaveName);  
326 -  
327 - if (device == null) {  
328 - TenantId tenantId = gateway.getTenantId();  
329 - device = new Device();  
330 - device.setTenantId(tenantId);  
331 - device.setName(requestMsg.getDeviceName());  
332 - device.setType(requestMsg.getDeviceType());  
333 - device.setCustomerId(gateway.getCustomerId());  
334 - DeviceProfile deviceProfile = deviceProfileCache.findOrCreateDeviceProfile(gateway.getTenantId(), DefaultSystemDataLoaderService.DEFAULT_DEVICE_TYPE);  
335 - device.setDeviceProfileId(deviceProfile.getId());  
336 - ObjectNode additionalInfo = JacksonUtil.newObjectNode();  
337 - additionalInfo.put(DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString());  
338 - device.setAdditionalInfo(additionalInfo);  
339 - Device savedDevice = deviceService.saveDevice(device);  
340 -  
341 -  
342 - //Thingskit function  
343 - ytDeviceService.saveSlaveDevice(savedDevice.getId().getId().toString(), savedDevice.getName(),deviceProfile.getId().getId().toString(), gateway.getId().getId().toString(),gateway.getCreatedTime());  
344 -  
345 -  
346 - tbClusterService.onDeviceUpdated(savedDevice, null);  
347 - device = savedDevice;  
348 -  
349 - relationService.saveRelationAsync(TenantId.SYS_TENANT_ID, new EntityRelation(gateway.getId(), device.getId(), "Created"));  
350 -  
351 - TbMsgMetaData metaData = new TbMsgMetaData();  
352 - CustomerId customerId = gateway.getCustomerId();  
353 - if (customerId != null && !customerId.isNullUid()) {  
354 - metaData.putValue("customerId", customerId.toString());  
355 - }  
356 - metaData.putValue("gatewayId", gatewayId.toString());  
357 -  
358 - DeviceId deviceId = device.getId();  
359 - ObjectNode entityNode = mapper.valueToTree(device);  
360 - TbMsg tbMsg = TbMsg.newMsg(DataConstants.ENTITY_CREATED, deviceId, customerId, metaData, TbMsgDataType.JSON, mapper.writeValueAsString(entityNode));  
361 - tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, null);  
362 - } else {  
363 - JsonNode deviceAdditionalInfo = device.getAdditionalInfo();  
364 - if (deviceAdditionalInfo == null) {  
365 - deviceAdditionalInfo = JacksonUtil.newObjectNode();  
366 - }  
367 - if (deviceAdditionalInfo.isObject() &&  
368 - (!deviceAdditionalInfo.has(DataConstants.LAST_CONNECTED_GATEWAY)  
369 - || !gatewayId.toString().equals(deviceAdditionalInfo.get(DataConstants.LAST_CONNECTED_GATEWAY).asText()))) {  
370 - ObjectNode newDeviceAdditionalInfo = (ObjectNode) deviceAdditionalInfo;  
371 - newDeviceAdditionalInfo.put(DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString());  
372 - Device savedDevice = deviceService.saveDevice(device);  
373 - tbClusterService.onDeviceUpdated(savedDevice, device);  
374 - }  
375 - }  
376 - GetOrCreateDeviceFromGatewayResponseMsg.Builder builder = GetOrCreateDeviceFromGatewayResponseMsg.newBuilder()  
377 - .setDeviceInfo(getDeviceInfoProto(device));  
378 - DeviceProfile deviceProfile = deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId());  
379 - if (deviceProfile != null) {  
380 - builder.setProfileBody(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile)));  
381 - } else {  
382 - log.warn("[{}] Failed to find device profile [{}] for device. ", device.getId(), device.getDeviceProfileId());  
383 - } 315 + if (!StringUtils.isEmpty(dbCred.getPassword())) {
  316 + if (StringUtils.isEmpty(clientCred.getPassword())) {
  317 + return BasicCredentialsValidationResult.PASSWORD_MISMATCH;
  318 + } else {
  319 + return dbCred.getPassword().equals(clientCred.getPassword())
  320 + ? VALID
  321 + : BasicCredentialsValidationResult.PASSWORD_MISMATCH;
  322 + }
  323 + }
  324 + return VALID;
  325 + }
  326 +
  327 + private ListenableFuture<TransportApiResponseMsg> handle(
  328 + GetOrCreateDeviceFromGatewayRequestMsg requestMsg) {
  329 + DeviceId gatewayId =
  330 + new DeviceId(new UUID(requestMsg.getGatewayIdMSB(), requestMsg.getGatewayIdLSB()));
  331 + ListenableFuture<Device> gatewayFuture =
  332 + deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, gatewayId);
  333 + return Futures.transform(
  334 + gatewayFuture,
  335 + gateway -> {
  336 + Lock deviceCreationLock =
  337 + deviceCreationLocks.computeIfAbsent(
  338 + requestMsg.getDeviceName(), id -> new ReentrantLock());
  339 + deviceCreationLock.lock();
  340 + try {
  341 +
  342 + // Thingskit function
  343 + String slaveName = requestMsg.getDeviceName();
  344 + if (gateway.getDeviceData().getTransportConfiguration().getType()
  345 + == DeviceTransportType.TCP) {
  346 + DeviceDTO iotDev =
  347 + ytDeviceService.findSlaveDevice(
  348 + gateway.getTenantId().getId().toString(),
  349 + gateway.getId().getId().toString(),
  350 + slaveName);
  351 + if (iotDev == null) {
  352 + GetOrCreateDeviceFromGatewayResponseMsg.Builder builder =
  353 + GetOrCreateDeviceFromGatewayResponseMsg.newBuilder();
384 return TransportApiResponseMsg.newBuilder() 354 return TransportApiResponseMsg.newBuilder()
385 - .setGetOrCreateDeviceResponseMsg(builder.build())  
386 - .build();  
387 - } catch (JsonProcessingException e) {  
388 - log.warn("[{}] Failed to lookup device by gateway id and name: [{}]", gatewayId, requestMsg.getDeviceName(), e);  
389 - throw new RuntimeException(e);  
390 - } finally {  
391 - deviceCreationLock.unlock(); 355 + .setGetOrCreateDeviceResponseMsg(builder.build())
  356 + .build();
  357 + }
  358 + slaveName = iotDev.getName();
392 } 359 }
393 - }, dbCallbackExecutorService);  
394 - }  
395 360
396 - private ListenableFuture<TransportApiResponseMsg> handle(ProvisionDeviceRequestMsg requestMsg) {  
397 - ListenableFuture<ProvisionResponse> provisionResponseFuture = null;  
398 - try {  
399 - provisionResponseFuture = Futures.immediateFuture(deviceProvisionService.provisionDevice(  
400 - new ProvisionRequest(  
401 - requestMsg.getDeviceName(),  
402 - requestMsg.getCredentialsType() != null ? DeviceCredentialsType.valueOf(requestMsg.getCredentialsType().name()) : null,  
403 - new ProvisionDeviceCredentialsData(requestMsg.getCredentialsDataProto().getValidateDeviceTokenRequestMsg().getToken(),  
404 - requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getClientId(),  
405 - requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getUserName(),  
406 - requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getPassword(),  
407 - requestMsg.getCredentialsDataProto().getValidateDeviceX509CertRequestMsg().getHash()),  
408 - new ProvisionDeviceProfileCredentials(  
409 - requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceKey(),  
410 - requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceSecret()))));  
411 - } catch (ProvisionFailedException e) {  
412 - return Futures.immediateFuture(getTransportApiResponseMsg(  
413 - new DeviceCredentials(),  
414 - TransportProtos.ResponseStatus.valueOf(e.getMessage())));  
415 - }  
416 - return Futures.transform(provisionResponseFuture, provisionResponse -> getTransportApiResponseMsg(provisionResponse.getDeviceCredentials(), TransportProtos.ResponseStatus.SUCCESS),  
417 - dbCallbackExecutorService);  
418 - } 361 + Device device =
  362 + deviceService.findDeviceByTenantIdAndName(gateway.getTenantId(), slaveName);
419 363
420 - private TransportApiResponseMsg getTransportApiResponseMsg(DeviceCredentials  
421 - deviceCredentials, TransportProtos.ResponseStatus status) {  
422 - if (!status.equals(TransportProtos.ResponseStatus.SUCCESS)) {  
423 - return TransportApiResponseMsg.newBuilder().setProvisionDeviceResponseMsg(TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build()).build();  
424 - }  
425 - TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse = TransportProtos.ProvisionDeviceResponseMsg.newBuilder()  
426 - .setCredentialsType(TransportProtos.CredentialsType.valueOf(deviceCredentials.getCredentialsType().name()))  
427 - .setStatus(status);  
428 - switch (deviceCredentials.getCredentialsType()) {  
429 - case ACCESS_TOKEN:  
430 - provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId());  
431 - break;  
432 - case MQTT_BASIC:  
433 - case X509_CERTIFICATE:  
434 - case LWM2M_CREDENTIALS:  
435 - provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsValue());  
436 - break;  
437 - }  
438 -  
439 - return TransportApiResponseMsg.newBuilder()  
440 - .setProvisionDeviceResponseMsg(provisionResponse.build()) 364 + if (device == null) {
  365 + TenantId tenantId = gateway.getTenantId();
  366 + device = new Device();
  367 + device.setTenantId(tenantId);
  368 + device.setName(requestMsg.getDeviceName());
  369 + device.setType(requestMsg.getDeviceType());
  370 + device.setCustomerId(gateway.getCustomerId());
  371 + DeviceProfile deviceProfile =
  372 + deviceProfileCache.findOrCreateDeviceProfile(
  373 + gateway.getTenantId(), DefaultSystemDataLoaderService.DEFAULT_DEVICE_TYPE);
  374 + device.setDeviceProfileId(deviceProfile.getId());
  375 + ObjectNode additionalInfo = JacksonUtil.newObjectNode();
  376 + additionalInfo.put(DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString());
  377 + device.setAdditionalInfo(additionalInfo);
  378 + Device savedDevice = deviceService.saveDevice(device);
  379 +
  380 + // Thingskit function
  381 + ytDeviceService.saveSlaveDevice(
  382 + savedDevice.getId().getId().toString(),
  383 + savedDevice.getName(),
  384 + deviceProfile.getId().getId().toString(),
  385 + gateway.getId().getId().toString(),
  386 + gateway.getCreatedTime());
  387 +
  388 + tbClusterService.onDeviceUpdated(savedDevice, null);
  389 + device = savedDevice;
  390 +
  391 + relationService.saveRelationAsync(
  392 + TenantId.SYS_TENANT_ID,
  393 + new EntityRelation(gateway.getId(), device.getId(), "Created"));
  394 +
  395 + TbMsgMetaData metaData = new TbMsgMetaData();
  396 + CustomerId customerId = gateway.getCustomerId();
  397 + if (customerId != null && !customerId.isNullUid()) {
  398 + metaData.putValue("customerId", customerId.toString());
  399 + }
  400 + metaData.putValue("gatewayId", gatewayId.toString());
  401 +
  402 + DeviceId deviceId = device.getId();
  403 + ObjectNode entityNode = mapper.valueToTree(device);
  404 + TbMsg tbMsg =
  405 + TbMsg.newMsg(
  406 + DataConstants.ENTITY_CREATED,
  407 + deviceId,
  408 + customerId,
  409 + metaData,
  410 + TbMsgDataType.JSON,
  411 + mapper.writeValueAsString(entityNode));
  412 + tbClusterService.pushMsgToRuleEngine(tenantId, deviceId, tbMsg, null);
  413 + } else {
  414 + JsonNode deviceAdditionalInfo = device.getAdditionalInfo();
  415 + if (deviceAdditionalInfo == null) {
  416 + deviceAdditionalInfo = JacksonUtil.newObjectNode();
  417 + }
  418 + if (deviceAdditionalInfo.isObject()
  419 + && (!deviceAdditionalInfo.has(DataConstants.LAST_CONNECTED_GATEWAY)
  420 + || !gatewayId
  421 + .toString()
  422 + .equals(
  423 + deviceAdditionalInfo
  424 + .get(DataConstants.LAST_CONNECTED_GATEWAY)
  425 + .asText()))) {
  426 + ObjectNode newDeviceAdditionalInfo = (ObjectNode) deviceAdditionalInfo;
  427 + newDeviceAdditionalInfo.put(
  428 + DataConstants.LAST_CONNECTED_GATEWAY, gatewayId.toString());
  429 + Device savedDevice = deviceService.saveDevice(device);
  430 + tbClusterService.onDeviceUpdated(savedDevice, device);
  431 + }
  432 + }
  433 + GetOrCreateDeviceFromGatewayResponseMsg.Builder builder =
  434 + GetOrCreateDeviceFromGatewayResponseMsg.newBuilder()
  435 + .setDeviceInfo(getDeviceInfoProto(device));
  436 + DeviceProfile deviceProfile =
  437 + deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId());
  438 + if (deviceProfile != null) {
  439 + builder.setProfileBody(
  440 + ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile)));
  441 + } else {
  442 + log.warn(
  443 + "[{}] Failed to find device profile [{}] for device. ",
  444 + device.getId(),
  445 + device.getDeviceProfileId());
  446 + }
  447 + return TransportApiResponseMsg.newBuilder()
  448 + .setGetOrCreateDeviceResponseMsg(builder.build())
441 .build(); 449 .build();
  450 + } catch (JsonProcessingException e) {
  451 + log.warn(
  452 + "[{}] Failed to lookup device by gateway id and name: [{}]",
  453 + gatewayId,
  454 + requestMsg.getDeviceName(),
  455 + e);
  456 + throw new RuntimeException(e);
  457 + } finally {
  458 + deviceCreationLock.unlock();
  459 + }
  460 + },
  461 + dbCallbackExecutorService);
  462 + }
  463 +
  464 + private ListenableFuture<TransportApiResponseMsg> handle(ProvisionDeviceRequestMsg requestMsg) {
  465 + ListenableFuture<ProvisionResponse> provisionResponseFuture = null;
  466 + try {
  467 + provisionResponseFuture =
  468 + Futures.immediateFuture(
  469 + deviceProvisionService.provisionDevice(
  470 + new ProvisionRequest(
  471 + requestMsg.getDeviceName(),
  472 + requestMsg.getCredentialsType() != null
  473 + ? DeviceCredentialsType.valueOf(requestMsg.getCredentialsType().name())
  474 + : null,
  475 + new ProvisionDeviceCredentialsData(
  476 + requestMsg
  477 + .getCredentialsDataProto()
  478 + .getValidateDeviceTokenRequestMsg()
  479 + .getToken(),
  480 + requestMsg
  481 + .getCredentialsDataProto()
  482 + .getValidateBasicMqttCredRequestMsg()
  483 + .getClientId(),
  484 + requestMsg
  485 + .getCredentialsDataProto()
  486 + .getValidateBasicMqttCredRequestMsg()
  487 + .getUserName(),
  488 + requestMsg
  489 + .getCredentialsDataProto()
  490 + .getValidateBasicMqttCredRequestMsg()
  491 + .getPassword(),
  492 + requestMsg
  493 + .getCredentialsDataProto()
  494 + .getValidateDeviceX509CertRequestMsg()
  495 + .getHash()),
  496 + new ProvisionDeviceProfileCredentials(
  497 + requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceKey(),
  498 + requestMsg
  499 + .getProvisionDeviceCredentialsMsg()
  500 + .getProvisionDeviceSecret()))));
  501 + } catch (ProvisionFailedException e) {
  502 + return Futures.immediateFuture(
  503 + getTransportApiResponseMsg(
  504 + new DeviceCredentials(), TransportProtos.ResponseStatus.valueOf(e.getMessage())));
442 } 505 }
443 -  
444 - private ListenableFuture<TransportApiResponseMsg> handle(GetEntityProfileRequestMsg requestMsg) {  
445 - EntityType entityType = EntityType.valueOf(requestMsg.getEntityType());  
446 - UUID entityUuid = new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB());  
447 - GetEntityProfileResponseMsg.Builder builder = GetEntityProfileResponseMsg.newBuilder();  
448 - if (entityType.equals(EntityType.DEVICE_PROFILE)) {  
449 - DeviceProfileId deviceProfileId = new DeviceProfileId(entityUuid);  
450 - DeviceProfile deviceProfile = deviceProfileCache.find(deviceProfileId);  
451 - builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile)));  
452 - } else if (entityType.equals(EntityType.TENANT)) {  
453 - TenantId tenantId = TenantId.fromUUID(entityUuid);  
454 - TenantProfile tenantProfile = tenantProfileCache.get(tenantId);  
455 - ApiUsageState state = apiUsageStateService.getApiUsageState(tenantId);  
456 - builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(tenantProfile)));  
457 - builder.setApiState(ByteString.copyFrom(dataDecodingEncodingService.encode(state)));  
458 - } else {  
459 - throw new RuntimeException("Invalid entity profile request: " + entityType);  
460 - }  
461 - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build()); 506 + return Futures.transform(
  507 + provisionResponseFuture,
  508 + provisionResponse ->
  509 + getTransportApiResponseMsg(
  510 + provisionResponse.getDeviceCredentials(), TransportProtos.ResponseStatus.SUCCESS),
  511 + dbCallbackExecutorService);
  512 + }
  513 +
  514 + private TransportApiResponseMsg getTransportApiResponseMsg(
  515 + DeviceCredentials deviceCredentials, TransportProtos.ResponseStatus status) {
  516 + if (!status.equals(TransportProtos.ResponseStatus.SUCCESS)) {
  517 + return TransportApiResponseMsg.newBuilder()
  518 + .setProvisionDeviceResponseMsg(
  519 + TransportProtos.ProvisionDeviceResponseMsg.newBuilder().setStatus(status).build())
  520 + .build();
462 } 521 }
463 -  
464 - private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceRequestMsg requestMsg) {  
465 - DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));  
466 - Device device = deviceService.findDeviceById(TenantId.SYS_TENANT_ID, deviceId);  
467 -  
468 - TransportApiResponseMsg responseMsg;  
469 - if (device != null) {  
470 - UUID deviceProfileId = device.getDeviceProfileId().getId();  
471 - responseMsg = TransportApiResponseMsg.newBuilder()  
472 - .setDeviceResponseMsg(TransportProtos.GetDeviceResponseMsg.newBuilder()  
473 - .setDeviceProfileIdMSB(deviceProfileId.getMostSignificantBits())  
474 - .setDeviceProfileIdLSB(deviceProfileId.getLeastSignificantBits())  
475 - .setDeviceTransportConfiguration(ByteString.copyFrom(  
476 - dataDecodingEncodingService.encode(device.getDeviceData().getTransportConfiguration())  
477 - )))  
478 - .build();  
479 - } else {  
480 - responseMsg = TransportApiResponseMsg.getDefaultInstance();  
481 - }  
482 -  
483 - return Futures.immediateFuture(responseMsg); 522 + TransportProtos.ProvisionDeviceResponseMsg.Builder provisionResponse =
  523 + TransportProtos.ProvisionDeviceResponseMsg.newBuilder()
  524 + .setCredentialsType(
  525 + TransportProtos.CredentialsType.valueOf(
  526 + deviceCredentials.getCredentialsType().name()))
  527 + .setStatus(status);
  528 + switch (deviceCredentials.getCredentialsType()) {
  529 + case ACCESS_TOKEN:
  530 + provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsId());
  531 + break;
  532 + case MQTT_BASIC:
  533 + case X509_CERTIFICATE:
  534 + case LWM2M_CREDENTIALS:
  535 + provisionResponse.setCredentialsValue(deviceCredentials.getCredentialsValue());
  536 + break;
484 } 537 }
485 538
486 - private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceCredentialsRequestMsg requestMsg) {  
487 - DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));  
488 - DeviceCredentials deviceCredentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, deviceId);  
489 -  
490 - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder()  
491 - .setDeviceCredentialsResponseMsg(TransportProtos.GetDeviceCredentialsResponseMsg.newBuilder()  
492 - .setDeviceCredentialsData(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceCredentials))))  
493 - .build()); 539 + return TransportApiResponseMsg.newBuilder()
  540 + .setProvisionDeviceResponseMsg(provisionResponse.build())
  541 + .build();
  542 + }
  543 +
  544 + private ListenableFuture<TransportApiResponseMsg> handle(GetEntityProfileRequestMsg requestMsg) {
  545 + EntityType entityType = EntityType.valueOf(requestMsg.getEntityType());
  546 + UUID entityUuid = new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB());
  547 + GetEntityProfileResponseMsg.Builder builder = GetEntityProfileResponseMsg.newBuilder();
  548 + if (entityType.equals(EntityType.DEVICE_PROFILE)) {
  549 + DeviceProfileId deviceProfileId = new DeviceProfileId(entityUuid);
  550 + DeviceProfile deviceProfile = deviceProfileCache.find(deviceProfileId);
  551 + builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile)));
  552 + } else if (entityType.equals(EntityType.TENANT)) {
  553 + TenantId tenantId = TenantId.fromUUID(entityUuid);
  554 + TenantProfile tenantProfile = tenantProfileCache.get(tenantId);
  555 + ApiUsageState state = apiUsageStateService.getApiUsageState(tenantId);
  556 + builder.setData(ByteString.copyFrom(dataDecodingEncodingService.encode(tenantProfile)));
  557 + builder.setApiState(ByteString.copyFrom(dataDecodingEncodingService.encode(state)));
  558 + } else {
  559 + throw new RuntimeException("Invalid entity profile request: " + entityType);
494 } 560 }
495 -  
496 -  
497 - private ListenableFuture<TransportApiResponseMsg> handle(GetResourceRequestMsg requestMsg) {  
498 - TenantId tenantId = TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));  
499 - ResourceType resourceType = ResourceType.valueOf(requestMsg.getResourceType());  
500 - String resourceKey = requestMsg.getResourceKey();  
501 - TransportProtos.GetResourceResponseMsg.Builder builder = TransportProtos.GetResourceResponseMsg.newBuilder();  
502 - TbResource resource = resourceService.getResource(tenantId, resourceType, resourceKey);  
503 -  
504 - if (resource == null && !tenantId.equals(TenantId.SYS_TENANT_ID)) {  
505 - resource = resourceService.getResource(TenantId.SYS_TENANT_ID, resourceType, resourceKey);  
506 - }  
507 -  
508 - if (resource != null) {  
509 - builder.setResource(ByteString.copyFrom(dataDecodingEncodingService.encode(resource)));  
510 - }  
511 -  
512 - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setResourceResponseMsg(builder).build()); 561 + return Futures.immediateFuture(
  562 + TransportApiResponseMsg.newBuilder().setEntityProfileResponseMsg(builder).build());
  563 + }
  564 +
  565 + private ListenableFuture<TransportApiResponseMsg> handle(GetDeviceRequestMsg requestMsg) {
  566 + DeviceId deviceId =
  567 + new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));
  568 + Device device = deviceService.findDeviceById(TenantId.SYS_TENANT_ID, deviceId);
  569 +
  570 + TransportApiResponseMsg responseMsg;
  571 + if (device != null) {
  572 + UUID deviceProfileId = device.getDeviceProfileId().getId();
  573 + responseMsg =
  574 + TransportApiResponseMsg.newBuilder()
  575 + .setDeviceResponseMsg(
  576 + TransportProtos.GetDeviceResponseMsg.newBuilder()
  577 + .setDeviceProfileIdMSB(deviceProfileId.getMostSignificantBits())
  578 + .setDeviceProfileIdLSB(deviceProfileId.getLeastSignificantBits())
  579 + .setDeviceTransportConfiguration(
  580 + ByteString.copyFrom(
  581 + dataDecodingEncodingService.encode(
  582 + device.getDeviceData().getTransportConfiguration()))))
  583 + .build();
  584 + } else {
  585 + responseMsg = TransportApiResponseMsg.getDefaultInstance();
513 } 586 }
514 587
515 - private ListenableFuture<TransportApiResponseMsg> handle(GetSnmpDevicesRequestMsg requestMsg) {  
516 - PageLink pageLink = new PageLink(requestMsg.getPageSize(), requestMsg.getPage());  
517 - PageData<UUID> result = deviceService.findDevicesIdsByDeviceProfileTransportType(DeviceTransportType.SNMP, pageLink);  
518 -  
519 - GetSnmpDevicesResponseMsg responseMsg = GetSnmpDevicesResponseMsg.newBuilder()  
520 - .addAllIds(result.getData().stream()  
521 - .map(UUID::toString)  
522 - .collect(Collectors.toList()))  
523 - .setHasNextPage(result.hasNext())  
524 - .build(); 588 + return Futures.immediateFuture(responseMsg);
  589 + }
  590 +
  591 + private ListenableFuture<TransportApiResponseMsg> handle(
  592 + GetDeviceCredentialsRequestMsg requestMsg) {
  593 + DeviceId deviceId =
  594 + new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));
  595 + DeviceCredentials deviceCredentials =
  596 + deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, deviceId);
  597 +
  598 + return Futures.immediateFuture(
  599 + TransportApiResponseMsg.newBuilder()
  600 + .setDeviceCredentialsResponseMsg(
  601 + TransportProtos.GetDeviceCredentialsResponseMsg.newBuilder()
  602 + .setDeviceCredentialsData(
  603 + ByteString.copyFrom(dataDecodingEncodingService.encode(deviceCredentials))))
  604 + .build());
  605 + }
  606 +
  607 + private ListenableFuture<TransportApiResponseMsg> handle(GetResourceRequestMsg requestMsg) {
  608 + TenantId tenantId =
  609 + TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));
  610 + ResourceType resourceType = ResourceType.valueOf(requestMsg.getResourceType());
  611 + String resourceKey = requestMsg.getResourceKey();
  612 + TransportProtos.GetResourceResponseMsg.Builder builder =
  613 + TransportProtos.GetResourceResponseMsg.newBuilder();
  614 + TbResource resource = resourceService.getResource(tenantId, resourceType, resourceKey);
  615 +
  616 + if (resource == null && !tenantId.equals(TenantId.SYS_TENANT_ID)) {
  617 + resource = resourceService.getResource(TenantId.SYS_TENANT_ID, resourceType, resourceKey);
  618 + }
525 619
526 - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder()  
527 - .setSnmpDevicesResponseMsg(responseMsg)  
528 - .build()); 620 + if (resource != null) {
  621 + builder.setResource(ByteString.copyFrom(dataDecodingEncodingService.encode(resource)));
529 } 622 }
530 623
531 - private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceCredentials credentials) {  
532 - return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, credentials.getDeviceId()), device -> {  
533 - if (device == null) {  
534 - log.trace("[{}] Failed to lookup device by id", credentials.getDeviceId());  
535 - return getEmptyTransportApiResponse(); 624 + return Futures.immediateFuture(
  625 + TransportApiResponseMsg.newBuilder().setResourceResponseMsg(builder).build());
  626 + }
  627 +
  628 + private ListenableFuture<TransportApiResponseMsg> handle(GetSnmpDevicesRequestMsg requestMsg) {
  629 + PageLink pageLink = new PageLink(requestMsg.getPageSize(), requestMsg.getPage());
  630 + PageData<UUID> result =
  631 + deviceService.findDevicesIdsByDeviceProfileTransportType(
  632 + DeviceTransportType.SNMP, pageLink);
  633 +
  634 + GetSnmpDevicesResponseMsg responseMsg =
  635 + GetSnmpDevicesResponseMsg.newBuilder()
  636 + .addAllIds(result.getData().stream().map(UUID::toString).collect(Collectors.toList()))
  637 + .setHasNextPage(result.hasNext())
  638 + .build();
  639 +
  640 + return Futures.immediateFuture(
  641 + TransportApiResponseMsg.newBuilder().setSnmpDevicesResponseMsg(responseMsg).build());
  642 + }
  643 +
  644 + private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceCredentials credentials) {
  645 + return Futures.transform(
  646 + deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, credentials.getDeviceId()),
  647 + device -> {
  648 + if (device == null) {
  649 + log.trace("[{}] Failed to lookup device by id", credentials.getDeviceId());
  650 + return getEmptyTransportApiResponse();
  651 + }
  652 + try {
  653 + ValidateDeviceCredentialsResponseMsg.Builder builder =
  654 + ValidateDeviceCredentialsResponseMsg.newBuilder();
  655 + builder.setDeviceInfo(getDeviceInfoProto(device));
  656 + DeviceProfile deviceProfile =
  657 + deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId());
  658 + if (deviceProfile != null) {
  659 + builder.setProfileBody(
  660 + ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile)));
  661 + } else {
  662 + log.warn(
  663 + "[{}] Failed to find device profile [{}] for device. ",
  664 + device.getId(),
  665 + device.getDeviceProfileId());
536 } 666 }
537 - try {  
538 - ValidateDeviceCredentialsResponseMsg.Builder builder = ValidateDeviceCredentialsResponseMsg.newBuilder();  
539 - builder.setDeviceInfo(getDeviceInfoProto(device));  
540 - DeviceProfile deviceProfile = deviceProfileCache.get(device.getTenantId(), device.getDeviceProfileId());  
541 - if (deviceProfile != null) {  
542 - builder.setProfileBody(ByteString.copyFrom(dataDecodingEncodingService.encode(deviceProfile)));  
543 - } else {  
544 - log.warn("[{}] Failed to find device profile [{}] for device. ", device.getId(), device.getDeviceProfileId());  
545 - }  
546 - if (!StringUtils.isEmpty(credentials.getCredentialsValue())) {  
547 - builder.setCredentialsBody(credentials.getCredentialsValue());  
548 - }  
549 - return TransportApiResponseMsg.newBuilder()  
550 - .setValidateCredResponseMsg(builder.build()).build();  
551 - } catch (JsonProcessingException e) {  
552 - log.warn("[{}] Failed to lookup device by id", credentials.getDeviceId(), e);  
553 - return getEmptyTransportApiResponse(); 667 + if (!StringUtils.isEmpty(credentials.getCredentialsValue())) {
  668 + builder.setCredentialsBody(credentials.getCredentialsValue());
554 } 669 }
555 - }, MoreExecutors.directExecutor()); 670 + return TransportApiResponseMsg.newBuilder()
  671 + .setValidateCredResponseMsg(builder.build())
  672 + .build();
  673 + } catch (JsonProcessingException e) {
  674 + log.warn("[{}] Failed to lookup device by id", credentials.getDeviceId(), e);
  675 + return getEmptyTransportApiResponse();
  676 + }
  677 + },
  678 + MoreExecutors.directExecutor());
  679 + }
  680 +
  681 + private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {
  682 + DeviceInfoProto.Builder builder =
  683 + DeviceInfoProto.newBuilder()
  684 + .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())
  685 + .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits())
  686 + .setCustomerIdMSB(
  687 + Optional.ofNullable(device.getCustomerId())
  688 + .map(customerId -> customerId.getId().getMostSignificantBits())
  689 + .orElse(0L))
  690 + .setCustomerIdLSB(
  691 + Optional.ofNullable(device.getCustomerId())
  692 + .map(customerId -> customerId.getId().getLeastSignificantBits())
  693 + .orElse(0L))
  694 + .setDeviceIdMSB(device.getId().getId().getMostSignificantBits())
  695 + .setDeviceIdLSB(device.getId().getId().getLeastSignificantBits())
  696 + .setDeviceName(device.getName())
  697 + .setDeviceType(device.getType())
  698 + .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits())
  699 + .setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits())
  700 + .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()));
  701 +
  702 + PowerSavingConfiguration psmConfiguration = null;
  703 + switch (device.getDeviceData().getTransportConfiguration().getType()) {
  704 + case LWM2M:
  705 + psmConfiguration =
  706 + (Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
  707 + break;
  708 + case COAP:
  709 + psmConfiguration =
  710 + (CoapDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();
  711 + break;
556 } 712 }
557 713
558 - private DeviceInfoProto getDeviceInfoProto(Device device) throws JsonProcessingException {  
559 - DeviceInfoProto.Builder builder = DeviceInfoProto.newBuilder()  
560 - .setTenantIdMSB(device.getTenantId().getId().getMostSignificantBits())  
561 - .setTenantIdLSB(device.getTenantId().getId().getLeastSignificantBits())  
562 - .setCustomerIdMSB(Optional.ofNullable(device.getCustomerId()).map(customerId -> customerId.getId().getMostSignificantBits()).orElse(0L))  
563 - .setCustomerIdLSB(Optional.ofNullable(device.getCustomerId()).map(customerId -> customerId.getId().getLeastSignificantBits()).orElse(0L))  
564 - .setDeviceIdMSB(device.getId().getId().getMostSignificantBits())  
565 - .setDeviceIdLSB(device.getId().getId().getLeastSignificantBits())  
566 - .setDeviceName(device.getName())  
567 - .setDeviceType(device.getType())  
568 - .setDeviceProfileIdMSB(device.getDeviceProfileId().getId().getMostSignificantBits())  
569 - .setDeviceProfileIdLSB(device.getDeviceProfileId().getId().getLeastSignificantBits())  
570 - .setAdditionalInfo(mapper.writeValueAsString(device.getAdditionalInfo()));  
571 -  
572 - PowerSavingConfiguration psmConfiguration = null;  
573 - switch (device.getDeviceData().getTransportConfiguration().getType()) {  
574 - case LWM2M:  
575 - psmConfiguration = (Lwm2mDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();  
576 - break;  
577 - case COAP:  
578 - psmConfiguration = (CoapDeviceTransportConfiguration) device.getDeviceData().getTransportConfiguration();  
579 - break;  
580 - }  
581 -  
582 - if (psmConfiguration != null) {  
583 - PowerMode powerMode = psmConfiguration.getPowerMode();  
584 - if (powerMode != null) {  
585 - builder.setPowerMode(powerMode.name());  
586 - if (powerMode.equals(PowerMode.PSM)) {  
587 - builder.setPsmActivityTimer(checkLong(psmConfiguration.getPsmActivityTimer()));  
588 - } else if (powerMode.equals(PowerMode.E_DRX)) {  
589 - builder.setEdrxCycle(checkLong(psmConfiguration.getEdrxCycle()));  
590 - builder.setPagingTransmissionWindow(checkLong(psmConfiguration.getPagingTransmissionWindow()));  
591 - }  
592 - } 714 + if (psmConfiguration != null) {
  715 + PowerMode powerMode = psmConfiguration.getPowerMode();
  716 + if (powerMode != null) {
  717 + builder.setPowerMode(powerMode.name());
  718 + if (powerMode.equals(PowerMode.PSM)) {
  719 + builder.setPsmActivityTimer(checkLong(psmConfiguration.getPsmActivityTimer()));
  720 + } else if (powerMode.equals(PowerMode.E_DRX)) {
  721 + builder.setEdrxCycle(checkLong(psmConfiguration.getEdrxCycle()));
  722 + builder.setPagingTransmissionWindow(
  723 + checkLong(psmConfiguration.getPagingTransmissionWindow()));
593 } 724 }
594 - return builder.build(); 725 + }
595 } 726 }
596 -  
597 - private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() {  
598 - return Futures.immediateFuture(getEmptyTransportApiResponse()); 727 + return builder.build();
  728 + }
  729 +
  730 + private ListenableFuture<TransportApiResponseMsg> getEmptyTransportApiResponseFuture() {
  731 + return Futures.immediateFuture(getEmptyTransportApiResponse());
  732 + }
  733 +
  734 + private TransportApiResponseMsg getEmptyTransportApiResponse() {
  735 + return TransportApiResponseMsg.newBuilder()
  736 + .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance())
  737 + .build();
  738 + }
  739 +
  740 + private ListenableFuture<TransportApiResponseMsg> handle(
  741 + TransportProtos.LwM2MRequestMsg requestMsg) {
  742 + if (requestMsg.hasRegistrationMsg()) {
  743 + return handleRegistration(requestMsg.getRegistrationMsg());
  744 + } else {
  745 + return Futures.immediateFailedFuture(new RuntimeException("Not supported!"));
599 } 746 }
600 -  
601 - private TransportApiResponseMsg getEmptyTransportApiResponse() {  
602 - return TransportApiResponseMsg.newBuilder()  
603 - .setValidateCredResponseMsg(ValidateDeviceCredentialsResponseMsg.getDefaultInstance()).build(); 747 + }
  748 +
  749 + private ListenableFuture<TransportApiResponseMsg> handle(
  750 + TransportProtos.GetOtaPackageRequestMsg requestMsg) {
  751 + TenantId tenantId =
  752 + TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));
  753 + DeviceId deviceId =
  754 + new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));
  755 + OtaPackageType otaPackageType = OtaPackageType.valueOf(requestMsg.getType());
  756 + Device device = deviceService.findDeviceById(tenantId, deviceId);
  757 +
  758 + if (device == null) {
  759 + return getEmptyTransportApiResponseFuture();
604 } 760 }
605 761
606 - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.LwM2MRequestMsg requestMsg) {  
607 - if (requestMsg.hasRegistrationMsg()) {  
608 - return handleRegistration(requestMsg.getRegistrationMsg());  
609 - } else {  
610 - return Futures.immediateFailedFuture(new RuntimeException("Not supported!"));  
611 - }  
612 - }  
613 -  
614 - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.GetOtaPackageRequestMsg requestMsg) {  
615 - TenantId tenantId = TenantId.fromUUID(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));  
616 - DeviceId deviceId = new DeviceId(new UUID(requestMsg.getDeviceIdMSB(), requestMsg.getDeviceIdLSB()));  
617 - OtaPackageType otaPackageType = OtaPackageType.valueOf(requestMsg.getType());  
618 - Device device = deviceService.findDeviceById(tenantId, deviceId);  
619 -  
620 - if (device == null) {  
621 - return getEmptyTransportApiResponseFuture();  
622 - }  
623 -  
624 - OtaPackageId otaPackageId = OtaPackageUtil.getOtaPackageId(device, otaPackageType);  
625 - if (otaPackageId == null) {  
626 - DeviceProfile deviceProfile = deviceProfileCache.find(device.getDeviceProfileId());  
627 - otaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, otaPackageType);  
628 - }  
629 -  
630 - TransportProtos.GetOtaPackageResponseMsg.Builder builder = TransportProtos.GetOtaPackageResponseMsg.newBuilder();  
631 -  
632 - if (otaPackageId == null) {  
633 - builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);  
634 - } else {  
635 - OtaPackageInfo otaPackageInfo = otaPackageService.findOtaPackageInfoById(tenantId, otaPackageId);  
636 -  
637 - if (otaPackageInfo == null) {  
638 - builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);  
639 - } else if (otaPackageInfo.hasUrl()) {  
640 - builder.setResponseStatus(TransportProtos.ResponseStatus.FAILURE);  
641 - log.trace("[{}] Can`t send OtaPackage with URL data!", otaPackageInfo.getId());  
642 - } else {  
643 - builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS);  
644 - builder.setOtaPackageIdMSB(otaPackageId.getId().getMostSignificantBits());  
645 - builder.setOtaPackageIdLSB(otaPackageId.getId().getLeastSignificantBits());  
646 - builder.setType(otaPackageInfo.getType().name());  
647 - builder.setTitle(otaPackageInfo.getTitle());  
648 - builder.setVersion(otaPackageInfo.getVersion());  
649 - builder.setFileName(otaPackageInfo.getFileName());  
650 - builder.setContentType(otaPackageInfo.getContentType());  
651 - if (!otaPackageDataCache.has(otaPackageId.toString())) {  
652 - OtaPackage otaPackage = otaPackageService.findOtaPackageById(tenantId, otaPackageId);  
653 - otaPackageDataCache.put(otaPackageId.toString(), otaPackage.getData().array());  
654 - }  
655 - }  
656 - }  
657 -  
658 - return Futures.immediateFuture(  
659 - TransportApiResponseMsg.newBuilder()  
660 - .setOtaPackageResponseMsg(builder.build())  
661 - .build()); 762 + OtaPackageId otaPackageId = OtaPackageUtil.getOtaPackageId(device, otaPackageType);
  763 + if (otaPackageId == null) {
  764 + DeviceProfile deviceProfile = deviceProfileCache.find(device.getDeviceProfileId());
  765 + otaPackageId = OtaPackageUtil.getOtaPackageId(deviceProfile, otaPackageType);
662 } 766 }
663 767
664 - private ListenableFuture<TransportApiResponseMsg> handleRegistration  
665 - (TransportProtos.LwM2MRegistrationRequestMsg msg) {  
666 - TenantId tenantId = TenantId.fromUUID(UUID.fromString(msg.getTenantId()));  
667 - String deviceName = msg.getEndpoint();  
668 - Lock deviceCreationLock = deviceCreationLocks.computeIfAbsent(deviceName, id -> new ReentrantLock());  
669 - deviceCreationLock.lock();  
670 - try {  
671 - Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName);  
672 - if (device == null) {  
673 - device = new Device();  
674 - device.setTenantId(tenantId);  
675 - device.setName(deviceName);  
676 - device.setType("LwM2M");  
677 - device = deviceService.saveDevice(device);  
678 - tbClusterService.onDeviceUpdated(device, null);  
679 - }  
680 - TransportProtos.LwM2MRegistrationResponseMsg registrationResponseMsg =  
681 - TransportProtos.LwM2MRegistrationResponseMsg.newBuilder()  
682 - .setDeviceInfo(getDeviceInfoProto(device)).build();  
683 - TransportProtos.LwM2MResponseMsg responseMsg = TransportProtos.LwM2MResponseMsg.newBuilder().setRegistrationMsg(registrationResponseMsg).build();  
684 - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setLwM2MResponseMsg(responseMsg).build());  
685 - } catch (JsonProcessingException e) {  
686 - log.warn("[{}][{}] Failed to lookup device by gateway id and name", tenantId, deviceName, e);  
687 - throw new RuntimeException(e);  
688 - } finally {  
689 - deviceCreationLock.unlock(); 768 + TransportProtos.GetOtaPackageResponseMsg.Builder builder =
  769 + TransportProtos.GetOtaPackageResponseMsg.newBuilder();
  770 +
  771 + if (otaPackageId == null) {
  772 + builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);
  773 + } else {
  774 + OtaPackageInfo otaPackageInfo =
  775 + otaPackageService.findOtaPackageInfoById(tenantId, otaPackageId);
  776 +
  777 + if (otaPackageInfo == null) {
  778 + builder.setResponseStatus(TransportProtos.ResponseStatus.NOT_FOUND);
  779 + } else if (otaPackageInfo.hasUrl()) {
  780 + builder.setResponseStatus(TransportProtos.ResponseStatus.FAILURE);
  781 + log.trace("[{}] Can`t send OtaPackage with URL data!", otaPackageInfo.getId());
  782 + } else {
  783 + builder.setResponseStatus(TransportProtos.ResponseStatus.SUCCESS);
  784 + builder.setOtaPackageIdMSB(otaPackageId.getId().getMostSignificantBits());
  785 + builder.setOtaPackageIdLSB(otaPackageId.getId().getLeastSignificantBits());
  786 + builder.setType(otaPackageInfo.getType().name());
  787 + builder.setTitle(otaPackageInfo.getTitle());
  788 + builder.setVersion(otaPackageInfo.getVersion());
  789 + builder.setFileName(otaPackageInfo.getFileName());
  790 + builder.setContentType(otaPackageInfo.getContentType());
  791 + if (!otaPackageDataCache.has(otaPackageId.toString())) {
  792 + OtaPackage otaPackage = otaPackageService.findOtaPackageById(tenantId, otaPackageId);
  793 + otaPackageDataCache.put(otaPackageId.toString(), otaPackage.getData().array());
690 } 794 }
  795 + }
691 } 796 }
692 797
693 - private Long checkLong(Long l) {  
694 - return l != null ? l : 0; 798 + return Futures.immediateFuture(
  799 + TransportApiResponseMsg.newBuilder().setOtaPackageResponseMsg(builder.build()).build());
  800 + }
  801 +
  802 + private ListenableFuture<TransportApiResponseMsg> handleRegistration(
  803 + TransportProtos.LwM2MRegistrationRequestMsg msg) {
  804 + TenantId tenantId = TenantId.fromUUID(UUID.fromString(msg.getTenantId()));
  805 + String deviceName = msg.getEndpoint();
  806 + Lock deviceCreationLock =
  807 + deviceCreationLocks.computeIfAbsent(deviceName, id -> new ReentrantLock());
  808 + deviceCreationLock.lock();
  809 + try {
  810 + Device device = deviceService.findDeviceByTenantIdAndName(tenantId, deviceName);
  811 + if (device == null) {
  812 + device = new Device();
  813 + device.setTenantId(tenantId);
  814 + device.setName(deviceName);
  815 + device.setType("LwM2M");
  816 + device = deviceService.saveDevice(device);
  817 + tbClusterService.onDeviceUpdated(device, null);
  818 + }
  819 + TransportProtos.LwM2MRegistrationResponseMsg registrationResponseMsg =
  820 + TransportProtos.LwM2MRegistrationResponseMsg.newBuilder()
  821 + .setDeviceInfo(getDeviceInfoProto(device))
  822 + .build();
  823 + TransportProtos.LwM2MResponseMsg responseMsg =
  824 + TransportProtos.LwM2MResponseMsg.newBuilder()
  825 + .setRegistrationMsg(registrationResponseMsg)
  826 + .build();
  827 + return Futures.immediateFuture(
  828 + TransportApiResponseMsg.newBuilder().setLwM2MResponseMsg(responseMsg).build());
  829 + } catch (JsonProcessingException e) {
  830 + log.warn("[{}][{}] Failed to lookup device by gateway id and name", tenantId, deviceName, e);
  831 + throw new RuntimeException(e);
  832 + } finally {
  833 + deviceCreationLock.unlock();
695 } 834 }
696 -  
697 -  
698 -  
699 - //Thingskit function  
700 - private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.ScriptProto requestMsg) {  
701 - List<TkDeviceScriptDTO> allScriptes = scriptService.getScriptes();  
702 - TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder();  
703 - allScriptes.forEach(  
704 - item -> {  
705 - UUID tenantId = UUID.fromString(item.getTenantId());  
706 - UUID id = UUID.fromString(item.getId());  
707 - responseBuilder.addScriptsResponseMsg(  
708 - TransportProtos.ScriptProto.newBuilder()  
709 - .setConvertJs(item.getConvertJs())  
710 - .setTenantIdLSB(tenantId.getLeastSignificantBits())  
711 - .setTenantIdMSB(tenantId.getMostSignificantBits())  
712 - .setScriptIdLSB(id.getLeastSignificantBits())  
713 - .setScriptIdMSB(id.getMostSignificantBits())  
714 - .setFunctionType(item.getScriptType().name())  
715 - .setStatus(item.getStatus()));  
716 - });  
717 - return Futures.immediateFuture(responseBuilder.build());  
718 - }  
719 - private ListenableFuture<TransportApiResponseMsg> handleGbt(TransportProtos.Gbt28181RequestMsg requestMsg) {  
720 - TransportProtos.Gbt28181ResponseMsg.Builder responseMsgBuilder =TransportProtos.Gbt28181ResponseMsg.newBuilder();  
721 - String tenantId = new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()).toString();  
722 - String tbDeviceId = new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB()).toString();  
723 - String type = requestMsg.getContextType();  
724 - switch (VideoCmdEnum.valueOf(type)){  
725 - case DeviceInfo:  
726 - Optional<SipDeviceDTO> camera = dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray());  
727 - camera.ifPresent(sip ->{  
728 - ytDeviceService.updateDeviceInfo(tenantId,tbDeviceId, FastIotConstants.DeviceAdditional.SIP,JacksonUtil.valueToTree(sip));  
729 - });  
730 -  
731 - break;  
732 - case Catalog:  
733 - Optional<List<VideoChanelDTO>> allChannel = dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray());  
734 - allChannel.ifPresent(d->{  
735 - channelService.clearDeviceChannel(d.get(0).getCameraCode());  
736 - List<TkVideoChannelEntity> chanel= d.stream().map(item -> item.getEntity(TkVideoChannelEntity.class)).collect(Collectors.toList());  
737 - channelService.insertBatch(chanel,chanel.size());  
738 - });  
739 - break;  
740 - default:  
741 - release(tenantId,tbDeviceId);  
742 -  
743 - }  
744 -// byte[] channaelMsgBytes = dataDecodingEncodingService.encode(channelDTO);  
745 -// responseMsgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes));  
746 - return Futures.immediateFuture(TransportApiResponseMsg.newBuilder().setGbt28181ResponseMsg(responseMsgBuilder.build()).build()); 835 + }
  836 +
  837 + private Long checkLong(Long l) {
  838 + return l != null ? l : 0;
  839 + }
  840 +
  841 + // Thingskit function
  842 + private ListenableFuture<TransportApiResponseMsg> handle(TransportProtos.ScriptProto requestMsg) {
  843 + List<TkDeviceScriptDTO> allScriptes = scriptService.getScriptes();
  844 + TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder();
  845 + allScriptes.forEach(
  846 + item -> {
  847 + UUID tenantId = UUID.fromString(item.getTenantId());
  848 + UUID id = UUID.fromString(item.getId());
  849 + responseBuilder.addScriptsResponseMsg(
  850 + TransportProtos.ScriptProto.newBuilder()
  851 + .setConvertJs(item.getConvertJs())
  852 + .setTenantIdLSB(tenantId.getLeastSignificantBits())
  853 + .setTenantIdMSB(tenantId.getMostSignificantBits())
  854 + .setScriptIdLSB(id.getLeastSignificantBits())
  855 + .setScriptIdMSB(id.getMostSignificantBits())
  856 + .setFunctionType(item.getScriptType().name())
  857 + .setStatus(item.getStatus()));
  858 + });
  859 + return Futures.immediateFuture(responseBuilder.build());
  860 + }
  861 +
  862 + private ListenableFuture<TransportApiResponseMsg> handleGbt(
  863 + TransportProtos.Gbt28181RequestMsg requestMsg) {
  864 + TransportProtos.Gbt28181ResponseMsg.Builder responseMsgBuilder =
  865 + TransportProtos.Gbt28181ResponseMsg.newBuilder();
  866 + String tenantId = new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()).toString();
  867 + String tbDeviceId =
  868 + new UUID(requestMsg.getEntityIdMSB(), requestMsg.getEntityIdLSB()).toString();
  869 + String type = requestMsg.getContextType();
  870 + switch (VideoCmdEnum.valueOf(type)) {
  871 + case DeviceInfo:
  872 + Optional<SipDeviceDTO> camera =
  873 + dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray());
  874 + camera.ifPresent(
  875 + sip -> {
  876 + ytDeviceService.updateDeviceInfo(
  877 + tenantId,
  878 + tbDeviceId,
  879 + FastIotConstants.DeviceAdditional.SIP,
  880 + JacksonUtil.valueToTree(sip));
  881 + });
  882 +
  883 + break;
  884 + case Catalog:
  885 + Optional<List<VideoChanelDTO>> allChannel =
  886 + dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray());
  887 + allChannel.ifPresent(
  888 + d -> {
  889 + channelService.clearDeviceChannel(d.get(0).getCameraCode());
  890 + List<TkVideoChannelEntity> chanel =
  891 + d.stream()
  892 + .map(item -> item.getEntity(TkVideoChannelEntity.class))
  893 + .collect(Collectors.toList());
  894 + channelService.insertBatch(chanel, chanel.size());
  895 + });
  896 + break;
  897 + default:
  898 + release(tenantId, tbDeviceId);
747 } 899 }
748 - private void release(String tenantId,String tbDeviceId){  
749 - DeviceDTO device = ytDeviceService.findDeviceInfoByTbDeviceId(tenantId,tbDeviceId);  
750 - Optional.ofNullable(device).ifPresent(dev->{  
751 - JsonNode sip = dev.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP);  
752 - if(!sip.isEmpty() && sip.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)){ 900 + // byte[] channaelMsgBytes = dataDecodingEncodingService.encode(channelDTO);
  901 + // responseMsgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes));
  902 + return Futures.immediateFuture(
  903 + TransportApiResponseMsg.newBuilder()
  904 + .setGbt28181ResponseMsg(responseMsgBuilder.build())
  905 + .build());
  906 + }
  907 +
  908 + private void release(String tenantId, String tbDeviceId) {
  909 + DeviceDTO device = ytDeviceService.findDeviceInfoByTbDeviceId(tenantId, tbDeviceId);
  910 + Optional.ofNullable(device)
  911 + .ifPresent(
  912 + dev -> {
  913 + JsonNode sip = dev.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP);
  914 + if (!sip.isEmpty() && sip.has(FastIotConstants.ZLMediaBody.CAMERA_CODE)) {
753 String cameraCode = sip.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText(); 915 String cameraCode = sip.get(FastIotConstants.ZLMediaBody.CAMERA_CODE).asText();
754 Optional<Set<String>> ssrcKeys = 916 Optional<Set<String>> ssrcKeys =
755 - videoStreamSessionManager.getSsrcTransactionCamaraKey(cameraCode);  
756 - ssrcKeys.ifPresent(all ->{  
757 - all.forEach(fullKey->{  
758 - videoStreamSessionManager.getSsrcTransaction(fullKey).ifPresent(ssrcTransaction -> {  
759 - mediaServerNodeService.releaseSsrc(  
760 - ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc());  
761 - mediaServerNodeService.closeRTPServer(  
762 - ssrcTransaction.getMediaServerId(), ssrcTransaction.getStream());  
763 - videoStreamSessionManager.remove(  
764 - cameraCode, ssrcTransaction.getChannelId(),  
765 - ssrcTransaction.getStream());  
766 - });  
767 - 917 + videoStreamSessionManager.getSsrcTransactionCamaraKey(cameraCode);
  918 + ssrcKeys.ifPresent(
  919 + all -> {
  920 + all.forEach(
  921 + fullKey -> {
  922 + videoStreamSessionManager
  923 + .getSsrcTransaction(fullKey)
  924 + .ifPresent(
  925 + ssrcTransaction -> {
  926 + mediaServerNodeService.releaseSsrc(
  927 + ssrcTransaction.getMediaServerId(),
  928 + ssrcTransaction.getSsrc());
  929 + mediaServerNodeService.closeRTPServer(
  930 + ssrcTransaction.getMediaServerId(),
  931 + ssrcTransaction.getStream());
  932 + videoStreamSessionManager.remove(
  933 + cameraCode,
  934 + ssrcTransaction.getChannelId(),
  935 + ssrcTransaction.getStream());
  936 + });
  937 + });
768 }); 938 });
769 - });  
770 - } 939 + }
  940 + });
  941 + }
  942 +
  943 + private ListenableFuture<TransportApiResponseMsg> handleGbtMedia(
  944 + TransportProtos.Gbt28181MediaServerMsg requestMsg) {
  945 + Optional<JsonNode> newMediaOpt =
  946 + dataDecodingEncodingService.decode(requestMsg.getProfile().toByteArray());
  947 + newMediaOpt.ifPresent(
  948 + json -> {
  949 + MediaServerDTO entity = JacksonUtil.treeToValue(json, MediaServerDTO.class);
  950 + MediaServerDTO queryEntity =
  951 + mediaServerService.findMediaServerInfoById(null, entity.getMediaServerId());
  952 + if (null == queryEntity) {
  953 + mediaServerService.saveMediaServer(entity);
  954 + } else {
  955 + entity.setId(queryEntity.getId());
  956 + mediaServerService.updateMediaServer(entity);
  957 + }
771 }); 958 });
772 959
773 - 960 + List<MediaServerDTO> allMediaKit = mediaServerService.getAllMediaKit();
  961 + Optional.ofNullable(allMediaKit)
  962 + .ifPresent(
  963 + all -> {
  964 + all.forEach(
  965 + dto -> {
  966 + String key = dto.getMediaServerId();
  967 + ZLMediaKitServerConfig zlMediaKitServerConfig = connectZlmServer(dto);
  968 + if (null != zlMediaKitServerConfig) {
  969 + zlMediaKitServerConfig.setIp(dto.getIp());
  970 + zlMediaKitServerConfig.setHttpPort(dto.getHttpPort());
  971 + zlMediaKitServerConfig.setTenantId(dto.getTenantId());
  972 + // 进行上线操作
  973 + mediaServerNodeService.zlmServerOnline(zlMediaKitServerConfig);
  974 + } else {
  975 + mediaServerNodeService.zlmServerOffline(key);
  976 + }
  977 + });
  978 + });
  979 + TransportApiResponseMsg.Builder responseBuilder = TransportApiResponseMsg.newBuilder();
  980 + responseBuilder.addGbt28181MediaServerMsg(TransportProtos.Gbt28181MediaServerMsg.newBuilder());
  981 + return Futures.immediateFuture(responseBuilder.build());
  982 + }
  983 +
  984 + /**
  985 + * 调用流媒体API接口获取流媒体配置
  986 + *
  987 + * @param mediaServerItem
  988 + * @return
  989 + */
  990 + private ZLMediaKitServerConfig connectZlmServer(MediaServerDTO mediaServerItem) {
  991 + log.info("启动流媒体【ZLMedia】验证,流媒体编号【{}】", mediaServerItem.getMediaServerId());
  992 + JsonNode responseJson = zlMediaKitRestFulUtils.getMediaServerConfig(mediaServerItem);
  993 + if (responseJson == null) {
  994 + log.error(
  995 + "流媒体【{}】服务地址【{}:{}】无法访问",
  996 + mediaServerItem.getMediaServerId(),
  997 + mediaServerItem.getIp(),
  998 + mediaServerItem.getHttpPort());
  999 + return null;
  1000 + }
  1001 + JsonNode data = responseJson.get(FastIotConstants.ZLMediaBody.DATA);
  1002 + if (data != null && !data.isEmpty()) {
  1003 + log.info(
  1004 + "流媒体【{}:{}】调用成功,响应内容【{}】", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), data);
  1005 + return org.thingsboard.server.common.data.yunteng.utils.JacksonUtil.convertValue(
  1006 + data.get(0), ZLMediaKitServerConfig.class);
  1007 + } else {
  1008 + log.error(
  1009 + "流媒体【{}:{}】调用失败,失败原因【{}】",
  1010 + mediaServerItem.getIp(),
  1011 + mediaServerItem.getHttpPort(),
  1012 + responseJson.get(FastIotConstants.ZLMediaBody.MSG));
774 } 1013 }
  1014 + return null;
  1015 + }
775 } 1016 }
1 -package org.thingsboard.server.service.yunteng.media;  
2 -  
3 -import com.fasterxml.jackson.databind.JsonNode;  
4 -import lombok.Getter;  
5 -import lombok.extern.slf4j.Slf4j;  
6 -import org.springframework.beans.factory.annotation.Value;  
7 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
8 -import org.springframework.stereotype.Component;  
9 -import org.thingsboard.server.common.data.id.EntityId;  
10 -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig;  
11 -import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;  
12 -import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO;  
13 -import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil;  
14 -import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils;  
15 -import org.thingsboard.server.dao.util.yunteng.ZLMediaKitTaskUtils;  
16 -import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerNodeService;  
17 -import org.thingsboard.server.dao.yunteng.service.media.TkMediaServerService;  
18 -import org.thingsboard.server.common.data.yunteng.config.media.MediaConfig;  
19 -import org.thingsboard.server.queue.util.TbCoreComponent;  
20 -  
21 -import javax.annotation.PostConstruct;  
22 -import java.util.List;  
23 -import java.util.Map;  
24 -import java.util.Optional;  
25 -  
26 -@Component("ZLMediaKitState")  
27 -@TbCoreComponent  
28 -@ConditionalOnExpression(  
29 - "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")  
30 -@Slf4j  
31 -public class ZLMediaKitStateRunner {  
32 - private final ZLMediaKitRestFulUtils zlMediaKitRestFulUtils;  
33 - private final TkMediaServerNodeService tkMediaServerNodeService;  
34 - private final TkMediaServerService tkMediaServerService;  
35 - private final MediaConfig mediaConfig;  
36 - private final ZLMediaKitTaskUtils zlMediaKitTaskUtils;  
37 - private final Map<String, Boolean> startGetMedia;  
38 -  
39 - @Value("${media.defaultStateCheckIntervalInSec}")  
40 - @Getter  
41 - private int defaultStateCheckIntervalInSec;  
42 -  
43 - public ZLMediaKitStateRunner(  
44 - ZLMediaKitRestFulUtils zlMediaKitRestFulUtils,  
45 - TkMediaServerNodeService tkMediaServerNodeService,  
46 - TkMediaServerService tkMediaServerService,  
47 - MediaConfig mediaConfig,  
48 - ZLMediaKitTaskUtils zlMediaKitTaskUtils,  
49 - Map<String, Boolean> startGetMedia) {  
50 - this.zlMediaKitRestFulUtils = zlMediaKitRestFulUtils;  
51 - this.tkMediaServerNodeService = tkMediaServerNodeService;  
52 - this.tkMediaServerService = tkMediaServerService;  
53 - this.mediaConfig = mediaConfig;  
54 - this.zlMediaKitTaskUtils = zlMediaKitTaskUtils;  
55 - this.startGetMedia = startGetMedia;  
56 - }  
57 -  
58 - @PostConstruct  
59 - public void init() {  
60 - updateDefaultMediaServer();  
61 - // 从数据库获取所有的流媒体信息  
62 - List<MediaServerDTO> dtoList = tkMediaServerService.getAllMediaKit();  
63 -  
64 - Optional.ofNullable(dtoList).ifPresent( all ->{  
65 - all.forEach(dto ->{  
66 - String key = dto.getMediaServerId();  
67 - startGetMedia.put(key, true);  
68 - zlMediaKitTaskUtils.startCronTask(  
69 - key,  
70 - () -> {  
71 - ZLMediaKitServerConfig zlMediaKitServerConfig = getMediaServerConfig(dto);  
72 - if (null != zlMediaKitServerConfig) {  
73 - startGetMedia.remove(dto.getMediaServerId());  
74 - zlMediaKitTaskUtils.stop(key);  
75 - zlMediaKitServerConfig.setIp(dto.getIp());  
76 - zlMediaKitServerConfig.setHttpPort(dto.getHttpPort());  
77 - zlMediaKitServerConfig.setTenantId(dto.getTenantId());  
78 - // 进行上线操作  
79 - tkMediaServerNodeService.zlmServerOnline(zlMediaKitServerConfig);  
80 - }  
81 - },  
82 - defaultStateCheckIntervalInSec);  
83 - });  
84 - });  
85 - }  
86 -  
87 - private void updateDefaultMediaServer() {  
88 - // 默认流媒体服务器  
89 - MediaServerDTO oldMediaServer = tkMediaServerService.findDefaultMediaServer();  
90 - MediaServerDTO defaultConfig = mediaConfig.getMediaSerItem();  
91 - if (oldMediaServer == null) {  
92 - defaultConfig.setTenantId(EntityId.NULL_UUID.toString());  
93 - }else{  
94 - defaultConfig.setId(oldMediaServer.getId());  
95 - defaultConfig.setTenantId(oldMediaServer.getTenantId());  
96 - }  
97 - tkMediaServerService.saveOrUpdateMediaServer(defaultConfig);  
98 - }  
99 -  
100 - /**  
101 - * 调用流媒体API接口获取流媒体配置  
102 - * @param mediaServerItem  
103 - * @return  
104 - */  
105 - private ZLMediaKitServerConfig getMediaServerConfig(MediaServerDTO mediaServerItem) {  
106 - log.error("启动流媒体【ZLMedia】验证,流媒体编号【{}】",mediaServerItem.getMediaServerId());  
107 - if (startGetMedia == null) {  
108 - return null;  
109 - }  
110 - if (!mediaServerItem.isDefaultServer()  
111 - && tkMediaServerNodeService.getOne(mediaServerItem.getMediaServerId()).isEmpty()) {  
112 - return null;  
113 - }  
114 - if (startGetMedia.get(mediaServerItem.getMediaServerId()) == null  
115 - || !startGetMedia.get(mediaServerItem.getMediaServerId())) {  
116 - return null;  
117 - }  
118 - JsonNode responseJson = zlMediaKitRestFulUtils.getMediaServerConfig(mediaServerItem);  
119 - if(responseJson == null){  
120 - log.error("流媒体【{}】服务地址【{}:{}】无法访问",mediaServerItem.getMediaServerId(),mediaServerItem.getIp(),mediaServerItem.getHttpPort());  
121 - return null;  
122 - }  
123 - JsonNode data = responseJson.get(FastIotConstants.ZLMediaBody.DATA);  
124 - if (data != null && !data.isEmpty()) {  
125 - log.error("流媒体【{}:{}】调用成功,响应内容【{}】",mediaServerItem.getIp(),mediaServerItem.getHttpPort(),data);  
126 - return JacksonUtil.convertValue(data.get(0), ZLMediaKitServerConfig.class);  
127 - }  
128 - log.error("流媒体【{}:{}】调用失败,失败原因【{}】",mediaServerItem.getIp(),mediaServerItem.getHttpPort(),responseJson.get(FastIotConstants.ZLMediaBody.MSG));  
129 - return null;  
130 - }  
131 -}  
@@ -721,6 +721,45 @@ transport: @@ -721,6 +721,45 @@ transport:
721 gbt28181: 721 gbt28181:
722 # Enable/disable gbt28181 transport protocol. 722 # Enable/disable gbt28181 transport protocol.
723 enabled: "${GBT28181_ENABLED:false}" 723 enabled: "${GBT28181_ENABLED:false}"
  724 + sip:
  725 + # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
  726 + # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
  727 + # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
  728 + # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
  729 + ip: ${GBT28181_SIP_IP:127.0.0.1}
  730 + # [可选] 28181服务监听的端口
  731 + port: ${GBT28181_SIP_PORT:5060}
  732 + #[可选]
  733 + id: ${GBT28181_SIP_ID:51010700599000000001}
  734 + # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
  735 + # 后两位为行业编码,定义参照附录D.3
  736 + # 3701020049标识山东济南历下区 信息行业接入
  737 + # [可选]
  738 + domain: ${GBT28181_SIP_DOMAIN:5101070059}
  739 + #[可选]
  740 + password: ${GBT28181_SIP_PASSWORD:61332286}
  741 + #zlm 默认服务器配置
  742 + media:
  743 + id: ${GBT28181_MEDIA_GENERAL_ID:D2okJWKKaQ5bX7Va}
  744 + # [必须修改] zlm服务器的内网IP
  745 + ip: ${GBT28181_MEDIA_IP:127.0.0.1}
  746 + # [必须修改] zlm服务器的http.port
  747 + http-port: ${GBT28181_MEDIA_HTTP_PORT:28080}
  748 + hook-ip: ${GBT28181_MEDIA_HOOK_IP:}
  749 + stream-ip: ${GBT28181_MEDIA_STREAM_IP:}
  750 + # [可选] zlm服务器的hook.admin_params=secret
  751 + secret: ${GBT28181_MEDIA_API_SECRET:QhrTN7k6HcDnt0YyeolwHwiVYDgIHPMZ}
  752 + # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
  753 + rtp:
  754 + # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
  755 + enable: true
  756 + # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
  757 + port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围
  758 + # [可选] 国标级联在此范围内选择端口发送媒体流,
  759 + send-port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围
  760 + # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
  761 + record-assist-port: 0
  762 + defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:10}"
724 tcp: 763 tcp:
725 # Enable/disable tcp transport protocol. 764 # Enable/disable tcp transport protocol.
726 enabled: "${TCP_ENABLED:true}" 765 enabled: "${TCP_ENABLED:true}"
@@ -1227,43 +1266,6 @@ logging: @@ -1227,43 +1266,6 @@ logging:
1227 frp: 1266 frp:
1228 server: 1267 server:
1229 address: ${FRP_SERVER_ADDRESS:http://127.0.0.1} 1268 address: ${FRP_SERVER_ADDRESS:http://127.0.0.1}
1230 -sip:  
1231 - # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,  
1232 - # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4  
1233 - # 如果不明白,就使用0.0.0.0,大部分情况都是可以的  
1234 - # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。  
1235 - ip: ${GBT28181_SIP_IP:127.0.0.1}  
1236 - # [可选] 28181服务监听的端口  
1237 - port: ${GBT28181_SIP_PORT:5060}  
1238 - #[可选]  
1239 - id: ${GBT28181_SIP_ID:51010700599000000001}  
1240 - # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)  
1241 - # 后两位为行业编码,定义参照附录D.3  
1242 - # 标识四川成都武侯下区 信息行业接入  
1243 - # [可选]  
1244 - domain: ${GBT28181_SIP_DOMAIN:5101070059}  
1245 - #[可选]  
1246 - password: ${GBT28181_SIP_PASSWORD:61332286}  
1247 -#zlm 默认服务器配置  
1248 -media:  
1249 - id: ${GBT28181_MEDIA_GENERAL_ID:D2okJWKKaQ5bX7Va}  
1250 - # [必须修改] zlm服务器的内网IP  
1251 - ip: ${GBT28181_MEDIA_IP:127.0.0.1}  
1252 - # [必须修改] zlm服务器的http.port  
1253 - http-port: ${GBT28181_MEDIA_HTTP_PORT:28080}  
1254 - # [可选] zlm服务器的hook.admin_params=secret  
1255 - secret: ${GBT28181_MEDIA_API_SECRET:QhrTN7k6HcDnt0YyeolwHwiVYDgIHPMZ}  
1256 - # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试  
1257 - rtp:  
1258 - # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输  
1259 - enable: true  
1260 - # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功  
1261 - port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围  
1262 - # [可选] 国标级联在此范围内选择端口发送媒体流,  
1263 - send-port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围  
1264 - # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用  
1265 - record-assist-port: 0  
1266 - defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:10}"  
1267 1269
1268 thingskit: 1270 thingskit:
1269 release: 1271 release:
@@ -680,6 +680,7 @@ message TransportApiRequestMsg { @@ -680,6 +680,7 @@ message TransportApiRequestMsg {
680 //Thingskit function 680 //Thingskit function
681 ScriptProto script = 14; 681 ScriptProto script = 14;
682 Gbt28181RequestMsg gbt28181RequestMsg = 15; 682 Gbt28181RequestMsg gbt28181RequestMsg = 15;
  683 + Gbt28181MediaServerMsg gbt28181MediaServerMsg = 16;
683 } 684 }
684 685
685 /* Response from ThingsBoard Core Service to Transport Service */ 686 /* Response from ThingsBoard Core Service to Transport Service */
@@ -698,6 +699,7 @@ message TransportApiResponseMsg { @@ -698,6 +699,7 @@ message TransportApiResponseMsg {
698 //Thingskit function 699 //Thingskit function
699 repeated ScriptProto scriptsResponseMsg = 11; 700 repeated ScriptProto scriptsResponseMsg = 11;
700 Gbt28181ResponseMsg gbt28181ResponseMsg = 12; 701 Gbt28181ResponseMsg gbt28181ResponseMsg = 12;
  702 + repeated Gbt28181MediaServerMsg gbt28181MediaServerMsg = 13;
701 } 703 }
702 704
703 /* Messages that are handled by ThingsBoard Core Service */ 705 /* Messages that are handled by ThingsBoard Core Service */
@@ -826,5 +828,11 @@ message Gbt28181ResponseMsg{ @@ -826,5 +828,11 @@ message Gbt28181ResponseMsg{
826 int64 entityIdMSB = 11; 828 int64 entityIdMSB = 11;
827 int64 entityIdLSB = 12; 829 int64 entityIdLSB = 12;
828 } 830 }
  831 +message Gbt28181MediaServerMsg{
  832 + bytes profile = 1;
  833 +}
  834 +message Gbt28181MediaResponseMsg{
  835 + repeated Gbt28181MediaServerMsg profiles = 1;
  836 +}
829 837
830 838
@@ -3,7 +3,6 @@ package org.thingsboard.server.common.data.yunteng.common.media; @@ -3,7 +3,6 @@ package org.thingsboard.server.common.data.yunteng.common.media;
3 import java.util.*; 3 import java.util.*;
4 import lombok.extern.slf4j.Slf4j; 4 import lombok.extern.slf4j.Slf4j;
5 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Autowired;
6 -import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;  
7 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
8 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; 7 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;
9 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 8 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
@@ -88,12 +87,14 @@ public class VideoStreamSessionManager { @@ -88,12 +87,14 @@ public class VideoStreamSessionManager {
88 public Optional<SsrcTransactionDTO> getSsrcTransaction(String fullKey) { 87 public Optional<SsrcTransactionDTO> getSsrcTransaction(String fullKey) {
89 return cacheUtils.get(cacheName, fullKey); 88 return cacheUtils.get(cacheName, fullKey);
90 } 89 }
91 - public Optional<SsrcTransactionDTO> getSsrcTransaction(String cameraCode, String channelId, String stream) {  
92 - Optional<Set<String>> keys =getSsrcTransactionChannelKey(cameraCode, channelId,stream);  
93 90
94 - if(keys.isPresent()){  
95 - Optional<String> fullKey =keys.get().stream().findFirst();  
96 - if(fullKey.isPresent()){ 91 + public Optional<SsrcTransactionDTO> getSsrcTransaction(
  92 + String cameraCode, String channelId, String stream) {
  93 + Optional<Set<String>> keys = getSsrcTransactionChannelKey(cameraCode, channelId, stream);
  94 +
  95 + if (keys.isPresent()) {
  96 + Optional<String> fullKey = keys.get().stream().findFirst();
  97 + if (fullKey.isPresent()) {
97 return getSsrcTransaction(fullKey.get()); 98 return getSsrcTransaction(fullKey.get());
98 } 99 }
99 } 100 }
1 -package org.thingsboard.server.common.data.yunteng.config.media;  
2 -  
3 -import lombok.Data;  
4 -import lombok.extern.slf4j.Slf4j;  
5 -import org.springframework.beans.factory.annotation.Value;  
6 -import org.springframework.boot.context.properties.ConfigurationProperties;  
7 -import org.springframework.stereotype.Component;  
8 -import org.springframework.util.ObjectUtils;  
9 -import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO;  
10 -  
11 -import java.net.InetAddress;  
12 -import java.net.UnknownHostException;  
13 -import java.util.Objects;  
14 -import java.util.regex.Pattern;  
15 -  
16 -/**  
17 - * 配置文件里面的流媒体配置信息  
18 - */  
19 -@ConfigurationProperties(prefix = "media")  
20 -@Component  
21 -@Data  
22 -@Slf4j  
23 -public class MediaConfig {  
24 - @Value("${media.id}")  
25 - private String mediaServerId;  
26 -  
27 - @Value("${media.ip}")  
28 - private String ip;  
29 -  
30 - @Value("${media.hook-ip:}")  
31 - private String hookIp;  
32 -  
33 - @Value("${sip.ip}")  
34 - private String sipIp;  
35 -  
36 - @Value("${sip.domain}")  
37 - private String sipDomain;  
38 -  
39 - @Value("${media.sdp-ip:${media.ip}}")  
40 - private String sdpIp;  
41 -  
42 - @Value("${media.stream-ip:${media.ip}}")  
43 - private String streamIp;  
44 -  
45 - @Value("${media.http-port}")  
46 - private Integer httpPort;  
47 -  
48 - @Value("${media.http-ssl-port:0}")  
49 - private Integer httpSslPort = 0;  
50 -  
51 - @Value("${media.rtmp-port:0}")  
52 - private Integer rtmpPort = 0;  
53 -  
54 - @Value("${media.rtmp-ssl-port:0}")  
55 - private Integer rtmpSslPort = 0;  
56 -  
57 - @Value("${media.rtp-proxy-port:0}")  
58 - private Integer rtpProxyPort = 0;  
59 -  
60 - @Value("${media.rtsp-port:0}")  
61 - private Integer rtspPort = 0;  
62 -  
63 - @Value("${media.rtsp-ssl-port:0}")  
64 - private Integer rtspSslPort = 0;  
65 -  
66 - @Value("${media.auto-config:true}")  
67 - private boolean autoConfig = true;  
68 -  
69 - @Value("${media.secret}")  
70 - private String secret;  
71 -  
72 - @Value("${media.rtp.enable}")  
73 - private boolean rtpEnable;  
74 -  
75 - @Value("${media.rtp.port-range}")  
76 - private String rtpPortRange;  
77 -  
78 - @Value("${media.rtp.send-port-range}")  
79 - private String rtpSendPortRange;  
80 -  
81 - @Value("${media.record-assist-port:0}")  
82 - private Integer recordAssistPort = 0;  
83 - private boolean status;  
84 -  
85 - public MediaServerDTO getMediaSerItem() {  
86 - MediaServerDTO mediaServerItem = new MediaServerDTO();  
87 - mediaServerItem.setMediaServerId(mediaServerId);  
88 - mediaServerItem.setIp(ip);  
89 - mediaServerItem.setDefaultServer(true);  
90 - mediaServerItem.setHookIp(getHookIp());  
91 - mediaServerItem.setSdpIp(getSdpIp());  
92 - mediaServerItem.setStreamIp(getStreamIp());  
93 - mediaServerItem.setHttpPort(httpPort);  
94 - mediaServerItem.setHttpSslPort(httpSslPort);  
95 - mediaServerItem.setRtmpPort(rtmpPort);  
96 - mediaServerItem.setRtmpSslPort(rtmpSslPort);  
97 - mediaServerItem.setRtpProxyPort(getRtpProxyPort());  
98 - mediaServerItem.setRtspPort(rtspPort);  
99 - mediaServerItem.setRtspSslPort(rtspSslPort);  
100 - mediaServerItem.setAutoConfig(autoConfig);  
101 - mediaServerItem.setSecret(secret);  
102 - mediaServerItem.setRtpEnable(rtpEnable);  
103 - mediaServerItem.setRtpPortRange(rtpPortRange);  
104 - mediaServerItem.setSendRtpPortRange(rtpSendPortRange);  
105 - mediaServerItem.setRecordAssistPort(recordAssistPort);  
106 - mediaServerItem.setHookAliveInterval(30.00f);  
107 - mediaServerItem.setStatus(status);  
108 - return mediaServerItem;  
109 - }  
110 -  
111 - public String getHookIp() {  
112 - if (ObjectUtils.isEmpty(hookIp)) {  
113 - return sipIp.split(",")[0];  
114 - } else {  
115 - return hookIp;  
116 - }  
117 - }  
118 -  
119 - public String getSipIp() {  
120 - if (sipIp == null) {  
121 - return this.ip;  
122 - } else {  
123 - return sipIp;  
124 - }  
125 - }  
126 -  
127 - public int getRtpProxyPort() {  
128 - return Objects.requireNonNullElse(rtpProxyPort, 0);  
129 - }  
130 -  
131 - public String getSdpIp() {  
132 - if (ObjectUtils.isEmpty(sdpIp)) {  
133 - return ip;  
134 - } else {  
135 - if (isValidIPAddress(sdpIp)) {  
136 - return sdpIp;  
137 - } else {  
138 - // 按照域名解析  
139 - String hostAddress = null;  
140 - try {  
141 - hostAddress = InetAddress.getByName(sdpIp).getHostAddress();  
142 - } catch (UnknownHostException e) {  
143 - log.error("[获取SDP IP]: 域名解析失败");  
144 - }  
145 - return hostAddress;  
146 - }  
147 - }  
148 - }  
149 -  
150 - public String getStreamIp() {  
151 - if (ObjectUtils.isEmpty(streamIp)) {  
152 - return ip;  
153 - } else {  
154 - return streamIp;  
155 - }  
156 - }  
157 -  
158 - private boolean isValidIPAddress(String ipAddress) {  
159 - if ((ipAddress != null) && (!ipAddress.isEmpty())) {  
160 - return Pattern.matches(  
161 - "^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$",  
162 - ipAddress);  
163 - }  
164 - return false;  
165 - }  
166 -}  
1 package org.thingsboard.server.common.data.yunteng.config.media; 1 package org.thingsboard.server.common.data.yunteng.config.media;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 -import org.springframework.boot.context.properties.ConfigurationProperties;  
5 import org.springframework.stereotype.Component; 4 import org.springframework.stereotype.Component;
6 5
7 -@ConfigurationProperties(prefix = "user-settings")  
8 @Component 6 @Component
9 @Data 7 @Data
10 public class UserSetting { 8 public class UserSetting {
11 - private String serverId = "000000";  
12 - private Boolean seniorSdp = Boolean.FALSE;  
13 - private Boolean pushAuthority = Boolean.TRUE;  
14 - private Boolean recordSip = Boolean.TRUE;  
15 - private Boolean recordPushLive = Boolean.TRUE;  
16 - private String recordPath = null;  
17 - private Boolean streamOnDemand = Boolean.TRUE;  
18 - private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE;  
19 - private Integer playTimeout = 30000; 9 + private String serverId = "000000";
  10 + private Boolean seniorSdp = Boolean.FALSE;
  11 + private Boolean pushAuthority = Boolean.TRUE;
  12 + private Boolean recordSip = Boolean.TRUE;
  13 + private Boolean recordPushLive = Boolean.TRUE;
  14 + private String recordPath = null;
  15 + private Boolean streamOnDemand = Boolean.TRUE;
  16 + private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE;
  17 + private Integer playTimeout = 30000;
20 } 18 }
@@ -3,8 +3,6 @@ package org.thingsboard.server.common.data.yunteng.dto.sip; @@ -3,8 +3,6 @@ package org.thingsboard.server.common.data.yunteng.dto.sip;
3 import io.swagger.annotations.ApiModelProperty; 3 import io.swagger.annotations.ApiModelProperty;
4 import lombok.Data; 4 import lombok.Data;
5 import lombok.EqualsAndHashCode; 5 import lombok.EqualsAndHashCode;
6 -import org.springframework.util.ObjectUtils;  
7 -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig;  
8 import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; 6 import org.thingsboard.server.common.data.yunteng.dto.TenantDTO;
9 7
10 @EqualsAndHashCode(callSuper = true) 8 @EqualsAndHashCode(callSuper = true)
@@ -63,11 +61,11 @@ public class MediaServerDTO extends TenantDTO { @@ -63,11 +61,11 @@ public class MediaServerDTO extends TenantDTO {
63 @ApiModelProperty(value = "流媒体服务器的状态") 61 @ApiModelProperty(value = "流媒体服务器的状态")
64 private boolean status; 62 private boolean status;
65 63
66 - @ApiModelProperty(value = "多端口RTP收流端口范围") 64 + @ApiModelProperty(value = "RTP收流端口范围")
67 private String rtpPortRange; 65 private String rtpPortRange;
68 66
69 - @ApiModelProperty(value = "RTP发流端口范围")  
70 - private String sendRtpPortRange; 67 + @ApiModelProperty(value = "RTP推流端口范围")
  68 + private String rtpSendPortRange;
71 69
72 @ApiModelProperty(value = "assist服务端口") 70 @ApiModelProperty(value = "assist服务端口")
73 private Integer recordAssistPort; 71 private Integer recordAssistPort;
@@ -81,33 +79,7 @@ public class MediaServerDTO extends TenantDTO { @@ -81,33 +79,7 @@ public class MediaServerDTO extends TenantDTO {
81 @ApiModelProperty(value = "当前使用到的端口") 79 @ApiModelProperty(value = "当前使用到的端口")
82 private Integer currentPort; 80 private Integer currentPort;
83 81
84 - public MediaServerDTO(){  
85 -  
86 - }  
87 - public MediaServerDTO(ZLMediaKitServerConfig zlmServerConfig, String sipIp) {  
88 - setId(zlmServerConfig.getGeneralMediaServerId());  
89 - ip = zlmServerConfig.getIp();  
90 - hookIp = ObjectUtils.isEmpty(zlmServerConfig.getHookIp()) ? sipIp : zlmServerConfig.getHookIp();  
91 - sdpIp =  
92 - ObjectUtils.isEmpty(zlmServerConfig.getSdpIp())  
93 - ? zlmServerConfig.getIp()  
94 - : zlmServerConfig.getSdpIp();  
95 - streamIp =  
96 - ObjectUtils.isEmpty(zlmServerConfig.getStreamIp())  
97 - ? zlmServerConfig.getIp()  
98 - : zlmServerConfig.getStreamIp();  
99 - httpPort = zlmServerConfig.getHttpPort();  
100 - httpSslPort = zlmServerConfig.getHttpSslPort();  
101 - rtmpPort = zlmServerConfig.getRtmpPort();  
102 - rtmpSslPort = zlmServerConfig.getRtmpSslPort();  
103 - rtpProxyPort = zlmServerConfig.getRtpProxyPort();  
104 - rtspPort = zlmServerConfig.getRtspPort();  
105 - rtspSslPort = zlmServerConfig.getRtspSslPort();  
106 - autoConfig = true; // 默认值true;  
107 - secret = zlmServerConfig.getApiSecret();  
108 - hookAliveInterval = zlmServerConfig.getHookAliveInterval();  
109 - rtpEnable = false; // 默认使用单端口;直到用户自己设置开启多端口  
110 - rtpPortRange = zlmServerConfig.getPortRange().replace("_", ","); // 默认使用30000,30500作为级联时发送流的端口号  
111 - recordAssistPort = 0; // 默认关闭  
112 - } 82 + private String hookEnable;
  83 +
  84 + public MediaServerDTO() {}
113 } 85 }
1 package org.thingsboard.server.common.data.yunteng.dto.sip; 1 package org.thingsboard.server.common.data.yunteng.dto.sip;
2 2
3 import io.swagger.annotations.ApiModelProperty; 3 import io.swagger.annotations.ApiModelProperty;
  4 +import java.io.Serializable;
4 import lombok.Data; 5 import lombok.Data;
5 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 6 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
6 7
7 -import java.io.Serializable;  
8 -  
9 @Data 8 @Data
10 public class SipDeviceDTO implements Serializable { 9 public class SipDeviceDTO implements Serializable {
11 @ApiModelProperty(value = "设备国标编号") 10 @ApiModelProperty(value = "设备国标编号")
@@ -37,6 +36,7 @@ public class SipDeviceDTO implements Serializable { @@ -37,6 +36,7 @@ public class SipDeviceDTO implements Serializable {
37 36
38 @ApiModelProperty(value = "是否开启ssrc校验,默认关闭,开启可以防止串流") 37 @ApiModelProperty(value = "是否开启ssrc校验,默认关闭,开启可以防止串流")
39 private boolean ssrcCheck = true; 38 private boolean ssrcCheck = true;
  39 +
40 @ApiModelProperty(value = "生产厂商") 40 @ApiModelProperty(value = "生产厂商")
41 private String manufacturer; 41 private String manufacturer;
42 42
@@ -48,12 +48,13 @@ public class SipDeviceDTO implements Serializable { @@ -48,12 +48,13 @@ public class SipDeviceDTO implements Serializable {
48 48
49 @ApiModelProperty(value = "固件版本") 49 @ApiModelProperty(value = "固件版本")
50 private String firmware; 50 private String firmware;
  51 +
51 public Integer getStreamModeForParam() { 52 public Integer getStreamModeForParam() {
52 if (FastIotConstants.StreamMode.UDP.equalsIgnoreCase(streamMode)) { 53 if (FastIotConstants.StreamMode.UDP.equalsIgnoreCase(streamMode)) {
53 return 0; 54 return 0;
54 - }else if (FastIotConstants.StreamMode.TCP_PASSIVE.equalsIgnoreCase(streamMode)) { 55 + } else if (FastIotConstants.StreamMode.TCP_PASSIVE.equalsIgnoreCase(streamMode)) {
55 return 1; 56 return 1;
56 - }else if (FastIotConstants.StreamMode.TCP_ACTIVE.equalsIgnoreCase(streamMode)) { 57 + } else if (FastIotConstants.StreamMode.TCP_ACTIVE.equalsIgnoreCase(streamMode)) {
57 return 2; 58 return 2;
58 } 59 }
59 return 0; 60 return 0;
@@ -2,6 +2,8 @@ package org.thingsboard.server.common.data.yunteng.utils; @@ -2,6 +2,8 @@ package org.thingsboard.server.common.data.yunteng.utils;
2 2
3 import lombok.extern.slf4j.Slf4j; 3 import lombok.extern.slf4j.Slf4j;
4 4
  5 +import java.util.regex.Pattern;
  6 +
5 /** 7 /**
6 * 数值格式相关工具类 8 * 数值格式相关工具类
7 */ 9 */
@@ -35,4 +37,18 @@ public class DataUtils { @@ -35,4 +37,18 @@ public class DataUtils {
35 return false; 37 return false;
36 } 38 }
37 } 39 }
  40 +
  41 + /**
  42 + * 是否有效的IP地址
  43 + * @param ipAddress IP地址字符串
  44 + * @return
  45 + */
  46 + public static boolean isIPAddress(String ipAddress) {
  47 + if ((ipAddress != null) && (!ipAddress.isEmpty())) {
  48 + return Pattern.matches(
  49 + "^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$",
  50 + ipAddress);
  51 + }
  52 + return false;
  53 + }
38 } 54 }
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,13 +10,11 @@ import javax.sip.address.AddressFactory;
10 import javax.sip.address.SipURI; 10 import javax.sip.address.SipURI;
11 import javax.sip.header.*; 11 import javax.sip.header.*;
12 import org.springframework.beans.factory.annotation.Autowired; 12 import org.springframework.beans.factory.annotation.Autowired;
13 -import org.springframework.stereotype.Component;  
14 -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig;  
15 -import org.thingsboard.server.common.data.yunteng.config.media.ThingsKitVersionConfig;  
16 -import org.thingsboard.server.transport.gbt28181.SipLayer; 13 +import org.thingsboard.server.transport.config.SipConfig;
  14 +import org.thingsboard.server.transport.config.ThingsKitVersionConfig;
  15 +import org.thingsboard.server.transport.gbt28181.sip.SipTransportService;
17 16
18 -@Component  
19 -public class AbstractSIPRequestProcess { 17 +public abstract class AbstractSIPRequestProcess {
20 @Autowired private SipConfig sipConfig; 18 @Autowired private SipConfig sipConfig;
21 @Autowired protected ThingsKitVersionConfig thingsKitVersionConfig; 19 @Autowired protected ThingsKitVersionConfig thingsKitVersionConfig;
22 20
@@ -41,7 +39,7 @@ public class AbstractSIPRequestProcess { @@ -41,7 +39,7 @@ public class AbstractSIPRequestProcess {
41 ViaHeader viaHeader = 39 ViaHeader viaHeader =
42 sipFactory 40 sipFactory
43 .createHeaderFactory() 41 .createHeaderFactory()
44 - .createViaHeader(SipLayer.getLocalIp(localIp), sipConfig.getPort(), transport, viaTag); 42 + .createViaHeader(SipTransportService.getLocalIp(localIp), sipConfig.getPort(), transport, viaTag);
45 viaHeader.setRPort(); 43 viaHeader.setRPort();
46 viaHeaders.add(viaHeader); 44 viaHeaders.add(viaHeader);
47 return viaHeaders; 45 return viaHeaders;
@@ -78,7 +76,7 @@ public class AbstractSIPRequestProcess { @@ -78,7 +76,7 @@ public class AbstractSIPRequestProcess {
78 throws PeerUnavailableException, ParseException { 76 throws PeerUnavailableException, ParseException {
79 SipURI sipUri = 77 SipURI sipUri =
80 buildRequestLineSipUri( 78 buildRequestLineSipUri(
81 - sipConfig.getId(), SipLayer.getLocalIp(localIp) + ":" + sipConfig.getPort()); 79 + sipConfig.getId(), SipTransportService.getLocalIp(localIp) + ":" + sipConfig.getPort());
82 Address concatAddress = sipFactory.createAddressFactory().createAddress(sipUri); 80 Address concatAddress = sipFactory.createAddressFactory().createAddress(sipUri);
83 return sipFactory.createHeaderFactory().createContactHeader(concatAddress); 81 return sipFactory.createHeaderFactory().createContactHeader(concatAddress);
84 } 82 }
@@ -15,12 +15,16 @@ import javax.sip.address.SipURI; @@ -15,12 +15,16 @@ import javax.sip.address.SipURI;
15 import javax.sip.header.*; 15 import javax.sip.header.*;
16 import javax.sip.message.Request; 16 import javax.sip.message.Request;
17 import javax.sip.message.Response; 17 import javax.sip.message.Response;
  18 +
  19 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
18 import org.springframework.stereotype.Component; 20 import org.springframework.stereotype.Component;
19 import org.thingsboard.server.common.data.yunteng.dto.sip.SipMessageHeaderDTO; 21 import org.thingsboard.server.common.data.yunteng.dto.sip.SipMessageHeaderDTO;
20 import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; 22 import org.thingsboard.server.transport.session.GbtDeviceSessionCtx;
21 import org.thingsboard.server.transport.util.TKSipUtils; 23 import org.thingsboard.server.transport.util.TKSipUtils;
22 24
23 @Component 25 @Component
  26 +@ConditionalOnExpression(
  27 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
24 public class SIPRequestHeaderProcess extends AbstractSIPRequestProcess { 28 public class SIPRequestHeaderProcess extends AbstractSIPRequestProcess {
25 public Request createMessageRequest( 29 public Request createMessageRequest(
26 GbtDeviceSessionCtx sessionCtx, 30 GbtDeviceSessionCtx sessionCtx,
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/cmd/SIPSender.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/SIPSender.java
1 -package org.thingsboard.server.transport; 1 +package org.thingsboard.server.transport.cmd;
2 2
3 import gov.nist.javax.sip.SipProviderImpl; 3 import gov.nist.javax.sip.SipProviderImpl;
4 import java.text.ParseException; 4 import java.text.ParseException;
@@ -11,15 +11,18 @@ import javax.sip.message.Request; @@ -11,15 +11,18 @@ import javax.sip.message.Request;
11 import javax.sip.message.Response; 11 import javax.sip.message.Response;
12 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
13 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
14 import org.springframework.stereotype.Component; 15 import org.springframework.stereotype.Component;
15 import org.springframework.util.ObjectUtils; 16 import org.springframework.util.ObjectUtils;
16 -import org.thingsboard.server.common.data.yunteng.config.media.ThingsKitVersionConfig;  
17 -import org.thingsboard.server.transport.gbt28181.SipLayer; 17 +import org.thingsboard.server.transport.config.ThingsKitVersionConfig;
  18 +import org.thingsboard.server.transport.gbt28181.sip.SipTransportService;
18 import org.thingsboard.server.transport.gbt28181.SipSubscribe; 19 import org.thingsboard.server.transport.gbt28181.SipSubscribe;
19 import org.thingsboard.server.transport.util.TKSipUtils; 20 import org.thingsboard.server.transport.util.TKSipUtils;
20 21
21 /** 发送SIP信息 */ 22 /** 发送SIP信息 */
22 @Component 23 @Component
  24 +@ConditionalOnExpression(
  25 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
23 @Slf4j 26 @Slf4j
24 public class SIPSender { 27 public class SIPSender {
25 28
@@ -80,7 +83,7 @@ public class SIPSender { @@ -80,7 +83,7 @@ public class SIPSender {
80 } 83 }
81 84
82 SipProviderImpl sipProvider = 85 SipProviderImpl sipProvider =
83 - TCP.equals(transport) ? SipLayer.getTcpSipProvider(ip) : SipLayer.getUdpSipProvider(ip); 86 + TCP.equals(transport) ? SipTransportService.getTcpSipProvider(ip) : SipTransportService.getUdpSipProvider(ip);
84 if (sipProvider == null) { 87 if (sipProvider == null) {
85 log.error("[发送信息失败] 未找到{}://{}的监听信息", transport, ip); 88 log.error("[发送信息失败] 未找到{}://{}的监听信息", transport, ip);
86 return; 89 return;
@@ -94,23 +97,23 @@ public class SIPSender { @@ -94,23 +97,23 @@ public class SIPSender {
94 97
95 public CallIdHeader getNewCallIdHeader(String ip, String transport) { 98 public CallIdHeader getNewCallIdHeader(String ip, String transport) {
96 if (ObjectUtils.isEmpty(transport)) { 99 if (ObjectUtils.isEmpty(transport)) {
97 - return SipLayer.getUdpSipProvider().getNewCallId(); 100 + return SipTransportService.getUdpSipProvider().getNewCallId();
98 } 101 }
99 SipProviderImpl sipProvider; 102 SipProviderImpl sipProvider;
100 if (ObjectUtils.isEmpty(ip)) { 103 if (ObjectUtils.isEmpty(ip)) {
101 sipProvider = 104 sipProvider =
102 transport.equalsIgnoreCase(TCP) 105 transport.equalsIgnoreCase(TCP)
103 - ? SipLayer.getTcpSipProvider()  
104 - : SipLayer.getUdpSipProvider(); 106 + ? SipTransportService.getTcpSipProvider()
  107 + : SipTransportService.getUdpSipProvider();
105 } else { 108 } else {
106 sipProvider = 109 sipProvider =
107 transport.equalsIgnoreCase(TCP) 110 transport.equalsIgnoreCase(TCP)
108 - ? SipLayer.getTcpSipProvider(ip)  
109 - : SipLayer.getUdpSipProvider(ip); 111 + ? SipTransportService.getTcpSipProvider(ip)
  112 + : SipTransportService.getUdpSipProvider(ip);
110 } 113 }
111 114
112 if (sipProvider == null) { 115 if (sipProvider == null) {
113 - sipProvider = SipLayer.getUdpSipProvider(); 116 + sipProvider = SipTransportService.getUdpSipProvider();
114 } 117 }
115 118
116 if (sipProvider != null) { 119 if (sipProvider != null) {
@@ -13,8 +13,7 @@ import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; @@ -13,8 +13,7 @@ import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;
13 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 13 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
14 import org.thingsboard.server.common.data.yunteng.dto.sip.*; 14 import org.thingsboard.server.common.data.yunteng.dto.sip.*;
15 import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum; 15 import org.thingsboard.server.common.data.yunteng.enums.VideoCmdEnum;
16 -import org.thingsboard.server.transport.SIPSender;  
17 -import org.thingsboard.server.transport.gbt28181.SipLayer; 16 +import org.thingsboard.server.transport.gbt28181.sip.SipTransportService;
18 import org.thingsboard.server.transport.gbt28181.SipSubscribe; 17 import org.thingsboard.server.transport.gbt28181.SipSubscribe;
19 import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; 18 import org.thingsboard.server.transport.session.GbtDeviceSessionCtx;
20 import org.thingsboard.server.transport.util.TKSipUtils; 19 import org.thingsboard.server.transport.util.TKSipUtils;
@@ -41,11 +40,11 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { @@ -41,11 +40,11 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService {
41 sessionCtx.getCameraCode()); 40 sessionCtx.getCameraCode());
42 CallIdHeader callIdHeader = 41 CallIdHeader callIdHeader =
43 sipSender.getNewCallIdHeader( 42 sipSender.getNewCallIdHeader(
44 - SipLayer.getLocalIp(sessionCtx.getLocalIp()), sessionCtx.getTransport()); 43 + SipTransportService.getLocalIp(sessionCtx.getLocalIp()), sessionCtx.getTransport());
45 Request request = 44 Request request =
46 headerProvider.createMessageRequest( 45 headerProvider.createMessageRequest(
47 sessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); 46 sessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader);
48 - sipSender.transmitRequest(SipLayer.getLocalIp(sessionCtx.getLocalIp()), request); 47 + sipSender.transmitRequest(SipTransportService.getLocalIp(sessionCtx.getLocalIp()), request);
49 } 48 }
50 49
51 @Override 50 @Override
@@ -63,13 +62,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { @@ -63,13 +62,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService {
63 deviceSessionCtx.getCameraCode()); 62 deviceSessionCtx.getCameraCode());
64 CallIdHeader callIdHeader = 63 CallIdHeader callIdHeader =
65 sipSender.getNewCallIdHeader( 64 sipSender.getNewCallIdHeader(
66 - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); 65 + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport());
67 Request request = 66 Request request =
68 headerProvider.createMessageRequest( 67 headerProvider.createMessageRequest(
69 deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); 68 deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader);
70 69
71 sipSender.transmitRequest( 70 sipSender.transmitRequest(
72 - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), request, errorEvent); 71 + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), request, errorEvent);
73 } 72 }
74 73
75 @Override 74 @Override
@@ -86,12 +85,12 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { @@ -86,12 +85,12 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService {
86 ptzCmd); 85 ptzCmd);
87 CallIdHeader callIdHeader = 86 CallIdHeader callIdHeader =
88 sipSender.getNewCallIdHeader( 87 sipSender.getNewCallIdHeader(
89 - SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport()); 88 + SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), deviceSessionCtx.getTransport());
90 Request request = 89 Request request =
91 headerProvider.createMessageRequest( 90 headerProvider.createMessageRequest(
92 deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader); 91 deviceSessionCtx, sipMessageHeaderDTO, xmlContent, callIdHeader);
93 92
94 - sipSender.transmitRequest(SipLayer.getLocalIp(deviceSessionCtx.getLocalIp()), request); 93 + sipSender.transmitRequest(SipTransportService.getLocalIp(deviceSessionCtx.getLocalIp()), request);
95 } 94 }
96 95
97 @Override 96 @Override
@@ -110,13 +109,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { @@ -110,13 +109,13 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService {
110 109
111 CallIdHeader callIdHeader = 110 CallIdHeader callIdHeader =
112 sipSender.getNewCallIdHeader( 111 sipSender.getNewCallIdHeader(
113 - SipLayer.getLocalIp(devSession.getLocalIp()), devSession.getTransport()); 112 + SipTransportService.getLocalIp(devSession.getLocalIp()), devSession.getTransport());
114 Request request = 113 Request request =
115 headerProvider.createInviteRequest( 114 headerProvider.createInviteRequest(
116 devSession, sipMessageHeaderDTO, channelId, content, callIdHeader, ssrc); 115 devSession, sipMessageHeaderDTO, channelId, content, callIdHeader, ssrc);
117 116
118 sipSender.transmitRequest( 117 sipSender.transmitRequest(
119 - SipLayer.getLocalIp(devSession.getLocalIp()), request, errorEvent, okEvent); 118 + SipTransportService.getLocalIp(devSession.getLocalIp()), request, errorEvent, okEvent);
120 } 119 }
121 120
122 @Override 121 @Override
@@ -144,7 +143,7 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService { @@ -144,7 +143,7 @@ public class TKSipCommanderServiceImpl implements TKSipCommanderService {
144 headerDTO.getViaTag(), 143 headerDTO.getViaTag(),
145 headerDTO.getFromTag(), 144 headerDTO.getFromTag(),
146 headerDTO.getToTag()); 145 headerDTO.getToTag());
147 - sipSender.transmitRequest(SipLayer.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent); 146 + sipSender.transmitRequest(SipTransportService.getLocalIp(device.getLocalIp()), byteRequest, null, okEvent);
148 } 147 }
149 148
150 private String buildMessageBodyQueryXml( 149 private String buildMessageBodyQueryXml(
  1 +package org.thingsboard.server.transport.config;
  2 +
  3 +import java.io.Serializable;
  4 +import lombok.Data;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.beans.factory.annotation.Value;
  7 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  8 +import org.springframework.boot.context.properties.ConfigurationProperties;
  9 +import org.springframework.stereotype.Component;
  10 +
  11 +/** 配置文件里面的流媒体配置信息 */
  12 +@ConfigurationProperties(prefix = "transport.gbt28181.media")
  13 +@Component
  14 +@ConditionalOnExpression(
  15 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
  16 +@Data
  17 +@Slf4j
  18 +public class MediaConfig implements Serializable {
  19 + @Value("${transport.gbt28181.media.id}")
  20 + private String mediaServerId;
  21 +
  22 + @Value("${transport.gbt28181.media.ip}")
  23 + private String ip;
  24 +
  25 + @Value("${transport.gbt28181.media.hook-ip:}")
  26 + private String hookIp;
  27 +
  28 + @Value("${transport.gbt28181.media.sdp-ip:${transport.gbt28181.media.ip}}")
  29 + private String sdpIp;
  30 +
  31 + @Value("${transport.gbt28181.media.stream-ip:${transport.gbt28181.media.ip}}")
  32 + private String streamIp;
  33 +
  34 + @Value("${transport.gbt28181.media.http-port}")
  35 + private Integer httpPort;
  36 +
  37 + @Value("${transport.gbt28181.media.http-ssl-port:0}")
  38 + private Integer httpSslPort = 0;
  39 +
  40 + @Value("${transport.gbt28181.media.rtmp-port:0}")
  41 + private Integer rtmpPort = 0;
  42 +
  43 + @Value("${transport.gbt28181.media.rtmp-ssl-port:0}")
  44 + private Integer rtmpSslPort = 0;
  45 +
  46 + @Value("${transport.gbt28181.media.rtp-proxy-port:0}")
  47 + private Integer rtpProxyPort = 0;
  48 +
  49 + @Value("${transport.gbt28181.media.rtsp-port:0}")
  50 + private Integer rtspPort = 0;
  51 +
  52 + @Value("${transport.gbt28181.media.rtsp-ssl-port:0}")
  53 + private Integer rtspSslPort = 0;
  54 +
  55 + @Value("${transport.gbt28181.media.auto-config:true}")
  56 + private boolean autoConfig = true;
  57 +
  58 + @Value("${transport.gbt28181.media.secret}")
  59 + private String secret;
  60 +
  61 + @Value("${transport.gbt28181.media.rtp.enable}")
  62 + private boolean rtpEnable;
  63 +
  64 + @Value("${transport.gbt28181.media.rtp.port-range}")
  65 + private String rtpPortRange;
  66 +
  67 + @Value("${transport.gbt28181.media.rtp.send-port-range}")
  68 + private String rtpSendPortRange;
  69 +
  70 + @Value("${transport.gbt28181.media.record-assist-port:0}")
  71 + private Integer recordAssistPort = 0;
  72 +
  73 + private boolean status;
  74 +}
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/config/SipConfig.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/yunteng/config/media/SipConfig.java
1 -package org.thingsboard.server.common.data.yunteng.config.media; 1 +package org.thingsboard.server.transport.config;
2 2
3 import lombok.Data; 3 import lombok.Data;
  4 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
4 import org.springframework.boot.context.properties.ConfigurationProperties; 5 import org.springframework.boot.context.properties.ConfigurationProperties;
5 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
6 7
7 -@ConfigurationProperties(prefix = "sip") 8 +@ConfigurationProperties(prefix = "transport.gbt28181.sip")
8 @Component 9 @Component
  10 +@ConditionalOnExpression(
  11 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
9 @Data 12 @Data
10 public class SipConfig { 13 public class SipConfig {
11 - private String ip;  
12 - private String showIp;  
13 - private Integer port;  
14 - private String id;  
15 - private String domain;  
16 - private String password;  
17 - Integer ptzSpeed = 50;  
18 - Integer registerTimeInterval = 120;  
19 - private boolean alarm; 14 + private String ip;
  15 + private String showIp;
  16 + private Integer port;
  17 + private String id;
  18 + private String domain;
  19 + private String password;
  20 + Integer ptzSpeed = 50;
  21 + Integer registerTimeInterval = 120;
  22 + private boolean alarm;
20 23
21 - public String getShowIp() {  
22 - if (this.showIp == null) {  
23 - return this.ip;  
24 - }  
25 - return showIp; 24 + public String getShowIp() {
  25 + if (this.showIp == null) {
  26 + return this.ip;
26 } 27 }
  28 + return showIp;
  29 + }
27 } 30 }
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/config/ThingsKitVersionConfig.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/yunteng/config/media/ThingsKitVersionConfig.java
1 -package org.thingsboard.server.common.data.yunteng.config.media; 1 +package org.thingsboard.server.transport.config;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 import org.springframework.beans.factory.annotation.Value; 4 import org.springframework.beans.factory.annotation.Value;
  5 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
5 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
6 7
7 @Component 8 @Component
  9 +@ConditionalOnExpression(
  10 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
8 @Data 11 @Data
9 public class ThingsKitVersionConfig { 12 public class ThingsKitVersionConfig {
10 @Value("${thingskit.release.version}") 13 @Value("${thingskit.release.version}")
@@ -13,12 +13,15 @@ import javax.sip.header.CallIdHeader; @@ -13,12 +13,15 @@ import javax.sip.header.CallIdHeader;
13 import javax.sip.message.Response; 13 import javax.sip.message.Response;
14 import org.slf4j.Logger; 14 import org.slf4j.Logger;
15 import org.slf4j.LoggerFactory; 15 import org.slf4j.LoggerFactory;
  16 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
16 import org.springframework.scheduling.annotation.Scheduled; 17 import org.springframework.scheduling.annotation.Scheduled;
17 import org.springframework.stereotype.Component; 18 import org.springframework.stereotype.Component;
18 -import org.thingsboard.server.transport.gbt28181.event.DeviceNotFoundEvent; 19 +import org.thingsboard.server.transport.gbt28181.sip.event.DeviceNotFoundEvent;
19 20
20 /** SIP订阅信息 */ 21 /** SIP订阅信息 */
21 @Component 22 @Component
  23 +@ConditionalOnExpression(
  24 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
22 public class SipSubscribe { 25 public class SipSubscribe {
23 26
24 private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class); 27 private final Logger logger = LoggerFactory.getLogger(SipSubscribe.class);
@@ -36,8 +36,6 @@ import javax.sip.header.HeaderFactory; @@ -36,8 +36,6 @@ import javax.sip.header.HeaderFactory;
36 import javax.sip.header.WWWAuthenticateHeader; 36 import javax.sip.header.WWWAuthenticateHeader;
37 import javax.sip.message.Request; 37 import javax.sip.message.Request;
38 import javax.sip.message.Response; 38 import javax.sip.message.Response;
39 -import org.slf4j.Logger;  
40 -import org.slf4j.LoggerFactory;  
41 39
42 /** Implements the HTTP digest authentication method server side functionality. */ 40 /** Implements the HTTP digest authentication method server side functionality. */
43 public class DigestServerAuthenticationHelper { 41 public class DigestServerAuthenticationHelper {
@@ -99,6 +97,7 @@ public class DigestServerAuthenticationHelper { @@ -99,6 +97,7 @@ public class DigestServerAuthenticationHelper {
99 } 97 }
100 return response; 98 return response;
101 } 99 }
  100 +
102 /** 101 /**
103 * Authenticate the inbound request. 102 * Authenticate the inbound request.
104 * 103 *
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/auth/RemoteAddressInfo.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/info/RemoteAddressInfo.java
1 -package org.thingsboard.server.transport.info; 1 +package org.thingsboard.server.transport.gbt28181.auth;
2 2
  3 +import lombok.Data;
  4 +
  5 +@Data
3 public class RemoteAddressInfo { 6 public class RemoteAddressInfo {
4 private String ip; 7 private String ip;
5 private int port; 8 private int port;
@@ -8,20 +11,4 @@ public class RemoteAddressInfo { @@ -8,20 +11,4 @@ public class RemoteAddressInfo {
8 this.ip = ip; 11 this.ip = ip;
9 this.port = port; 12 this.port = port;
10 } 13 }
11 -  
12 - public String getIp() {  
13 - return ip;  
14 - }  
15 -  
16 - public void setIp(String ip) {  
17 - this.ip = ip;  
18 - }  
19 -  
20 - public int getPort() {  
21 - return port;  
22 - }  
23 -  
24 - public void setPort(int port) {  
25 - this.port = port;  
26 - }  
27 } 14 }
@@ -7,6 +7,7 @@ import java.util.*; @@ -7,6 +7,7 @@ import java.util.*;
7 import java.util.concurrent.ConcurrentHashMap; 7 import java.util.concurrent.ConcurrentHashMap;
8 import java.util.concurrent.TimeUnit; 8 import java.util.concurrent.TimeUnit;
9 9
  10 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
10 import org.springframework.scheduling.annotation.Scheduled; 11 import org.springframework.scheduling.annotation.Scheduled;
11 import org.springframework.stereotype.Component; 12 import org.springframework.stereotype.Component;
12 import org.thingsboard.server.common.data.yunteng.dto.sip.CatalogDataDTO; 13 import org.thingsboard.server.common.data.yunteng.dto.sip.CatalogDataDTO;
@@ -16,6 +17,8 @@ import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; @@ -16,6 +17,8 @@ import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO;
16 import org.thingsboard.server.common.data.yunteng.enums.CatalogDataStatusEnum; 17 import org.thingsboard.server.common.data.yunteng.enums.CatalogDataStatusEnum;
17 18
18 @Component 19 @Component
  20 +@ConditionalOnExpression(
  21 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
19 public class CatalogDataCatch { 22 public class CatalogDataCatch {
20 23
21 public static Map<String, CatalogDataDTO> data = new ConcurrentHashMap<>(); 24 public static Map<String, CatalogDataDTO> data = new ConcurrentHashMap<>();
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/session/GbtTransportContext.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/GbtTransportContext.java
1 -package org.thingsboard.server.transport; 1 +package org.thingsboard.server.transport.gbt28181.session;
2 2
3 -import gov.nist.core.HostPort;  
4 import io.netty.handler.ssl.SslHandler; 3 import io.netty.handler.ssl.SslHandler;
5 -import java.net.InetSocketAddress;  
6 import java.util.concurrent.Executors; 4 import java.util.concurrent.Executors;
7 import java.util.concurrent.ScheduledExecutorService; 5 import java.util.concurrent.ScheduledExecutorService;
8 import java.util.concurrent.atomic.AtomicInteger; 6 import java.util.concurrent.atomic.AtomicInteger;
@@ -10,13 +8,11 @@ import javax.annotation.PostConstruct; @@ -10,13 +8,11 @@ import javax.annotation.PostConstruct;
10 import lombok.Getter; 8 import lombok.Getter;
11 import lombok.Setter; 9 import lombok.Setter;
12 import lombok.extern.slf4j.Slf4j; 10 import lombok.extern.slf4j.Slf4j;
13 -import org.springframework.beans.factory.annotation.Autowired;  
14 import org.springframework.beans.factory.annotation.Value; 11 import org.springframework.beans.factory.annotation.Value;
15 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 12 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
16 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
17 import org.thingsboard.common.util.ThingsBoardThreadFactory; 14 import org.thingsboard.common.util.ThingsBoardThreadFactory;
18 import org.thingsboard.server.common.transport.TransportContext; 15 import org.thingsboard.server.common.transport.TransportContext;
19 -import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor;  
20 16
21 @Slf4j 17 @Slf4j
22 @Component 18 @Component
@@ -24,8 +20,6 @@ import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor; @@ -24,8 +20,6 @@ import org.thingsboard.server.transport.adaptors.GbtTransportAdaptor;
24 "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") 20 "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
25 public class GbtTransportContext extends TransportContext { 21 public class GbtTransportContext extends TransportContext {
26 22
27 - /** 注入多种数据协议处理器,例如:modbus等 */  
28 - @Getter @Autowired private GbtTransportAdaptor jsonAdaptor;  
29 23
30 @Getter 24 @Getter
31 @Value("${transport.tcp.netty.max_payload_size}") 25 @Value("${transport.tcp.netty.max_payload_size}")
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/DefaultProperties.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/DefaultProperties.java
1 -package org.thingsboard.server.transport.gbt28181; 1 +package org.thingsboard.server.transport.gbt28181.sip;
2 2
3 import lombok.extern.log4j.Log4j; 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 import javax.sip.RequestEvent; 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 import javax.sip.ResponseEvent; 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,7 +11,7 @@
11 * express or implied. See the License for the specific language governing permissions and 11 * express or implied. See the License for the specific language governing permissions and
12 * limitations under the License. 12 * limitations under the License.
13 */ 13 */
14 -package org.thingsboard.server.transport.gbt28181; 14 +package org.thingsboard.server.transport.gbt28181.sip;
15 15
16 import gov.nist.javax.sip.SipProviderImpl; 16 import gov.nist.javax.sip.SipProviderImpl;
17 import gov.nist.javax.sip.SipStackImpl; 17 import gov.nist.javax.sip.SipStackImpl;
@@ -26,20 +26,20 @@ import org.springframework.stereotype.Service; @@ -26,20 +26,20 @@ import org.springframework.stereotype.Service;
26 import org.springframework.util.ObjectUtils; 26 import org.springframework.util.ObjectUtils;
27 import org.thingsboard.server.common.data.DataConstants; 27 import org.thingsboard.server.common.data.DataConstants;
28 import org.thingsboard.server.common.data.TbTransportService; 28 import org.thingsboard.server.common.data.TbTransportService;
29 -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig;  
30 -import org.thingsboard.server.transport.SIPProvider; 29 +import org.thingsboard.server.transport.gbt28181.sip.processor.SIPProvider;
  30 +import org.thingsboard.server.transport.config.SipConfig;
31 31
32 /** 32 /**
33 * @author Andrew Shvayka 33 * @author Andrew Shvayka
34 */ 34 */
35 -@Service("GBT28181TransportService")  
36 -@ConditionalOnExpression("'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')") 35 +@Service()
  36 +@ConditionalOnExpression(
  37 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
37 @Slf4j 38 @Slf4j
38 -public class SipLayer implements TbTransportService { 39 +public class SipTransportService implements TbTransportService {
39 private static final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); 40 private static final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
40 private static final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); 41 private static final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
41 - @Autowired  
42 - private SIPProvider sipProvider; 42 + @Autowired private SIPProvider sipProvider;
43 43
44 @Autowired private SipConfig sipConfig; 44 @Autowired private SipConfig sipConfig;
45 45
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/event/DeviceNotFoundEvent.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/event/DeviceNotFoundEvent.java
1 -package org.thingsboard.server.transport.gbt28181.event; 1 +package org.thingsboard.server.transport.gbt28181.sip.event;
2 2
3 import java.util.EventObject; 3 import java.util.EventObject;
4 import javax.sip.Dialog; 4 import javax.sip.Dialog;
  5 +import lombok.Getter;
  6 +import lombok.Setter;
5 7
  8 +@Getter
  9 +@Setter
6 public class DeviceNotFoundEvent extends EventObject { 10 public class DeviceNotFoundEvent extends EventObject {
7 11
8 private String callId; 12 private String callId;
@@ -16,12 +20,4 @@ public class DeviceNotFoundEvent extends EventObject { @@ -16,12 +20,4 @@ public class DeviceNotFoundEvent extends EventObject {
16 public DeviceNotFoundEvent(Dialog dialog) { 20 public DeviceNotFoundEvent(Dialog dialog) {
17 super(dialog); 21 super(dialog);
18 } 22 }
19 -  
20 - public String getCallId() {  
21 - return callId;  
22 - }  
23 -  
24 - public void setCallId(String callId) {  
25 - this.callId = callId;  
26 - }  
27 } 23 }
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/ITimeoutProcessor.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/ITimeoutProcessor.java
1 -package org.thingsboard.server.transport.gbt28181; 1 +package org.thingsboard.server.transport.gbt28181.sip.processor;
2 2
3 import javax.sip.TimeoutEvent; 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 import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED; 3 import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_CLOSED;
4 import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_OPEN; 4 import static org.thingsboard.server.common.transport.service.DefaultTransportService.SESSION_EVENT_MSG_OPEN;
@@ -40,8 +40,6 @@ import org.thingsboard.server.common.data.DeviceTransportType; @@ -40,8 +40,6 @@ import org.thingsboard.server.common.data.DeviceTransportType;
40 import org.thingsboard.server.common.data.StringUtils; 40 import org.thingsboard.server.common.data.StringUtils;
41 import org.thingsboard.server.common.data.id.DeviceId; 41 import org.thingsboard.server.common.data.id.DeviceId;
42 import org.thingsboard.server.common.data.rpc.RpcStatus; 42 import org.thingsboard.server.common.data.rpc.RpcStatus;
43 -import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager;  
44 -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig;  
45 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; 43 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;
46 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 44 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
47 import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; 45 import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO;
@@ -58,11 +56,16 @@ import org.thingsboard.server.common.transport.auth.SessionInfoCreator; @@ -58,11 +56,16 @@ import org.thingsboard.server.common.transport.auth.SessionInfoCreator;
58 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; 56 import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
59 import org.thingsboard.server.common.transport.util.DataDecodingEncodingService; 57 import org.thingsboard.server.common.transport.util.DataDecodingEncodingService;
60 import org.thingsboard.server.gen.transport.TransportProtos; 58 import org.thingsboard.server.gen.transport.TransportProtos;
  59 +import org.thingsboard.server.transport.gbt28181.session.GbtTransportContext;
61 import org.thingsboard.server.transport.cmd.SIPRequestHeaderProcess; 60 import org.thingsboard.server.transport.cmd.SIPRequestHeaderProcess;
62 import org.thingsboard.server.transport.cmd.TKSipCommanderService; 61 import org.thingsboard.server.transport.cmd.TKSipCommanderService;
  62 +import org.thingsboard.server.transport.config.MediaConfig;
  63 +import org.thingsboard.server.transport.config.SipConfig;
63 import org.thingsboard.server.transport.gbt28181.*; 64 import org.thingsboard.server.transport.gbt28181.*;
64 import org.thingsboard.server.transport.gbt28181.auth.DigestServerAuthenticationHelper; 65 import org.thingsboard.server.transport.gbt28181.auth.DigestServerAuthenticationHelper;
65 -import org.thingsboard.server.transport.info.RemoteAddressInfo; 66 +import org.thingsboard.server.transport.gbt28181.sip.ISIPRequestProcessor;
  67 +import org.thingsboard.server.transport.gbt28181.sip.ISIPResponseProcessor;
  68 +import org.thingsboard.server.transport.gbt28181.auth.RemoteAddressInfo;
66 import org.thingsboard.server.transport.session.GbtDeviceSessionCtx; 69 import org.thingsboard.server.transport.session.GbtDeviceSessionCtx;
67 import org.thingsboard.server.transport.util.TKSipUtils; 70 import org.thingsboard.server.transport.util.TKSipUtils;
68 import org.thingsboard.server.transport.util.TKXmlUtil; 71 import org.thingsboard.server.transport.util.TKXmlUtil;
@@ -81,6 +84,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -81,6 +84,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
81 84
82 private final SIPRequestHeaderProcess headerProvider; 85 private final SIPRequestHeaderProcess headerProvider;
83 private final SipConfig sipConfig; 86 private final SipConfig sipConfig;
  87 + private final MediaConfig mediaConfig;
84 private final UserSetting userSetting; 88 private final UserSetting userSetting;
85 private final TKSipCommanderService commanderService; 89 private final TKSipCommanderService commanderService;
86 private final DataDecodingEncodingService encodingService; 90 private final DataDecodingEncodingService encodingService;
@@ -93,7 +97,9 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -93,7 +97,9 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
93 97
94 @Getter 98 @Getter
95 private final ConcurrentHashMap<DeviceId, String> onlineDevice = new ConcurrentHashMap<>(); 99 private final ConcurrentHashMap<DeviceId, String> onlineDevice = new ConcurrentHashMap<>();
96 - private final ConcurrentHashMap<String, List<VideoChanelDTO>> deviceNewChanel = new ConcurrentHashMap<>(); 100 +
  101 + private final ConcurrentHashMap<String, List<VideoChanelDTO>> deviceNewChanel =
  102 + new ConcurrentHashMap<>();
97 private static final Map<String, ISIPRequestProcessor> requestProcessorMap = 103 private static final Map<String, ISIPRequestProcessor> requestProcessorMap =
98 new ConcurrentHashMap<>(); 104 new ConcurrentHashMap<>();
99 private static final Map<String, ISIPResponseProcessor> responseProcessorMap = 105 private static final Map<String, ISIPResponseProcessor> responseProcessorMap =
@@ -101,6 +107,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -101,6 +107,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
101 private static ITimeoutProcessor timeoutProcessor; 107 private static ITimeoutProcessor timeoutProcessor;
102 108
103 private final SipSubscribe sipSubscribe; 109 private final SipSubscribe sipSubscribe;
  110 +
104 /** 111 /**
105 * 添加 request订阅 112 * 添加 request订阅
106 * 113 *
@@ -159,7 +166,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -159,7 +166,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
159 CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); 166 CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
160 String methodName = cseqHeader.getMethod(); 167 String methodName = cseqHeader.getMethod();
161 SIPResponse request = (SIPResponse) responseEvent.getResponse(); 168 SIPResponse request = (SIPResponse) responseEvent.getResponse();
162 - log.debug( 169 + log.info(
163 "收到ResponseEvent,方法类型【{}】,状态码【{}】,事件内容【{}】", 170 "收到ResponseEvent,方法类型【{}】,状态码【{}】,事件内容【{}】",
164 methodName, 171 methodName,
165 status, 172 status,
@@ -178,8 +185,11 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -178,8 +185,11 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
178 default: 185 default:
179 log.debug("不支持的响应类型【{}】", method); 186 log.debug("不支持的响应类型【{}】", method);
180 } 187 }
181 - if (status != Response.UNAUTHORIZED && responseEvent.getResponse() != null && sipSubscribe.getOkSubscribesSize() > 0 ) {  
182 - CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME); 188 + if (status != Response.UNAUTHORIZED
  189 + && responseEvent.getResponse() != null
  190 + && sipSubscribe.getOkSubscribesSize() > 0) {
  191 + CallIdHeader callIdHeader =
  192 + (CallIdHeader) responseEvent.getResponse().getHeader(CallIdHeader.NAME);
183 if (callIdHeader != null) { 193 if (callIdHeader != null) {
184 SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); 194 SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId());
185 if (subscribe != null) { 195 if (subscribe != null) {
@@ -192,20 +202,26 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -192,20 +202,26 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
192 } else if ((status >= Response.TRYING) && (status < Response.OK)) { 202 } else if ((status >= Response.TRYING) && (status < Response.OK)) {
193 // 增加其它无需回复的响应,如101、180等 203 // 增加其它无需回复的响应,如101、180等
194 } else { 204 } else {
195 - log.error("收到ResponseEvent,设备【{}】,状态码【{}】,失败原因【{}】,ResponseEvent内容【{}】",response.getHeader(FromHeader.NAME),status, response.getReasonPhrase(),response.getRawContent() == null ? null : new String(response.getRawContent()));  
196 - if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0 ) {  
197 - CallIdHeader callIdHeader = (CallIdHeader)responseEvent.getResponse().getHeader(CallIdHeader.NAME);  
198 - if (callIdHeader != null) {  
199 - SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());  
200 - if (subscribe != null) {  
201 - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);  
202 - subscribe.response(eventResult);  
203 - sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());  
204 - } 205 + log.error(
  206 + "收到ResponseEvent,设备【{}】,状态码【{}】,失败原因【{}】,ResponseEvent内容【{}】",
  207 + response.getHeader(FromHeader.NAME),
  208 + status,
  209 + response.getReasonPhrase(),
  210 + response.getRawContent() == null ? null : new String(response.getRawContent()));
  211 + if (responseEvent.getResponse() != null && sipSubscribe.getErrorSubscribesSize() > 0) {
  212 + CallIdHeader callIdHeader =
  213 + (CallIdHeader) responseEvent.getResponse().getHeader(CallIdHeader.NAME);
  214 + if (callIdHeader != null) {
  215 + SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId());
  216 + if (subscribe != null) {
  217 + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent);
  218 + subscribe.response(eventResult);
  219 + sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId());
205 } 220 }
  221 + }
206 } 222 }
207 if (responseEvent.getDialog() != null) { 223 if (responseEvent.getDialog() != null) {
208 - responseEvent.getDialog().delete(); 224 + responseEvent.getDialog().delete();
209 } 225 }
210 } 226 }
211 } 227 }
@@ -219,7 +235,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -219,7 +235,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
219 public void processRequest(RequestEvent requestEvent) { 235 public void processRequest(RequestEvent requestEvent) {
220 String methodName = requestEvent.getRequest().getMethod(); 236 String methodName = requestEvent.getRequest().getMethod();
221 SIPRequest request = (SIPRequest) requestEvent.getRequest(); 237 SIPRequest request = (SIPRequest) requestEvent.getRequest();
222 - log.debug( 238 + log.info(
223 "收到RequestEvent,方法类型【{}】,事件内容【{}】", 239 "收到RequestEvent,方法类型【{}】,事件内容【{}】",
224 methodName, 240 methodName,
225 request.getRawContent() == null ? null : new String(request.getRawContent())); 241 request.getRawContent() == null ? null : new String(request.getRawContent()));
@@ -307,14 +323,15 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -307,14 +323,15 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
307 */ 323 */
308 void processResponseMessage(GbtDeviceSessionCtx ctx, ResponseEvent msg) {} 324 void processResponseMessage(GbtDeviceSessionCtx ctx, ResponseEvent msg) {}
309 325
310 - private String cameraAddress(SIPRequest request){ 326 + private String cameraAddress(SIPRequest request) {
311 RemoteAddressInfo remoteAddressInfo = 327 RemoteAddressInfo remoteAddressInfo =
312 - TKSipUtils.getRemoteAddressFromRequest(  
313 - request, userSetting.getSipUseSourceIpAsRemoteAddress()); 328 + TKSipUtils.getRemoteAddressFromRequest(
  329 + request, userSetting.getSipUseSourceIpAsRemoteAddress());
314 String hostAddress = remoteAddressInfo.getIp(); 330 String hostAddress = remoteAddressInfo.getIp();
315 int remotePort = remoteAddressInfo.getPort(); 331 int remotePort = remoteAddressInfo.getPort();
316 return hostAddress + ":" + remotePort; 332 return hostAddress + ":" + remotePort;
317 } 333 }
  334 +
318 /** 335 /**
319 * 处理请求事件的MESSAGE消息,根据XML数据的根节点名称进行分发 336 * 处理请求事件的MESSAGE消息,根据XML数据的根节点名称进行分发
320 * 337 *
@@ -342,7 +359,8 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -342,7 +359,8 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
342 } 359 }
343 if (ctx != null) { 360 if (ctx != null) {
344 if (!ctx.getHostAddress().equals(cameraAddress(request))) { 361 if (!ctx.getHostAddress().equals(cameraAddress(request))) {
345 - log.trace("摄像头【{}/{}】IP或端口已过期,断开连接", ctx.getDeviceInfo().getDeviceName(),ctx.getCameraCode()); 362 + log.trace(
  363 + "摄像头【{}/{}】IP或端口已过期,断开连接", ctx.getDeviceInfo().getDeviceName(), ctx.getCameraCode());
346 deviceSessions.remove(ctx.getCameraCode()); 364 deviceSessions.remove(ctx.getCameraCode());
347 responseAck(request, Response.OK); 365 responseAck(request, Response.OK);
348 return; 366 return;
@@ -454,7 +472,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -454,7 +472,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
454 transportService.deregisterSession(ds.getSessionInfo()); 472 transportService.deregisterSession(ds.getSessionInfo());
455 transportService.process(ds.getSessionInfo(), SESSION_EVENT_MSG_CLOSED, null); 473 transportService.process(ds.getSessionInfo(), SESSION_EVENT_MSG_CLOSED, null);
456 try { 474 try {
457 - cameraResponseRequest(ds, request, null,null); 475 + cameraResponseRequest(ds, request, null, null);
458 } catch (InvalidArgumentException | ParseException | SipException e) { 476 } catch (InvalidArgumentException | ParseException | SipException e) {
459 throw new RuntimeException(e); 477 throw new RuntimeException(e);
460 } 478 }
@@ -515,24 +533,25 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -515,24 +533,25 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
515 case DeviceInfo: 533 case DeviceInfo:
516 SipDeviceDTO cameraInfoDTO = TKXmlUtil.cameraInfoBuilder(rootElement); 534 SipDeviceDTO cameraInfoDTO = TKXmlUtil.cameraInfoBuilder(rootElement);
517 cameraInfoDTO.setHostAddress(request.getViaHost() + ":" + request.getViaPort()); 535 cameraInfoDTO.setHostAddress(request.getViaHost() + ":" + request.getViaPort());
  536 + cameraInfoDTO.setMediaServerId(mediaConfig.getMediaServerId());
518 byte[] cameraMsgBytes = encodingService.encode(cameraInfoDTO); 537 byte[] cameraMsgBytes = encodingService.encode(cameraInfoDTO);
519 msgBuilder.setContext(ByteString.copyFrom(cameraMsgBytes)); 538 msgBuilder.setContext(ByteString.copyFrom(cameraMsgBytes));
520 break; 539 break;
521 case Catalog: 540 case Catalog:
522 List<VideoChanelDTO> channelDTO = TKXmlUtil.channelInfoBuilder(devSession, rootElement); 541 List<VideoChanelDTO> channelDTO = TKXmlUtil.channelInfoBuilder(devSession, rootElement);
523 String cameraCode = devSession.getCameraCode(); 542 String cameraCode = devSession.getCameraCode();
524 - int channelNum =1;  
525 - if(!channelDTO.isEmpty()){  
526 - channelNum = channelDTO.get(0).getSumNum();  
527 - List<VideoChanelDTO> itemChanel = new ArrayList<>();  
528 - if(deviceNewChanel.containsKey(cameraCode)){  
529 - itemChanel =deviceNewChanel.get(cameraCode);  
530 - }else{  
531 - deviceNewChanel.put(cameraCode,itemChanel);  
532 - }  
533 - itemChanel.addAll(channelDTO);  
534 - }  
535 - if(channelNum == deviceNewChanel.get(cameraCode).size()){ 543 + int channelNum = 1;
  544 + if (!channelDTO.isEmpty()) {
  545 + channelNum = channelDTO.get(0).getSumNum();
  546 + List<VideoChanelDTO> itemChanel = new ArrayList<>();
  547 + if (deviceNewChanel.containsKey(cameraCode)) {
  548 + itemChanel = deviceNewChanel.get(cameraCode);
  549 + } else {
  550 + deviceNewChanel.put(cameraCode, itemChanel);
  551 + }
  552 + itemChanel.addAll(channelDTO);
  553 + }
  554 + if (channelNum == deviceNewChanel.get(cameraCode).size()) {
536 byte[] channaelMsgBytes = encodingService.encode(deviceNewChanel.get(cameraCode)); 555 byte[] channaelMsgBytes = encodingService.encode(deviceNewChanel.get(cameraCode));
537 msgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes)); 556 msgBuilder.setContext(ByteString.copyFrom(channaelMsgBytes));
538 deviceNewChanel.remove(cameraCode); 557 deviceNewChanel.remove(cameraCode);
@@ -644,7 +663,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -644,7 +663,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
644 return; 663 return;
645 } 664 }
646 DeviceProfile profile = msg.getDeviceProfile(); 665 DeviceProfile profile = msg.getDeviceProfile();
647 - if(profile.getTransportType() != DeviceTransportType.GBT28181){ 666 + if (profile.getTransportType() != DeviceTransportType.GBT28181) {
648 return; 667 return;
649 } 668 }
650 GbtDeviceSessionCtx deviceSessionCtx = 669 GbtDeviceSessionCtx deviceSessionCtx =
@@ -698,12 +717,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -698,12 +717,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
698 .build(); 717 .build();
699 commanderService.queryDeviceInfo(deviceSessionCtx, deviceInfoHeader); 718 commanderService.queryDeviceInfo(deviceSessionCtx, deviceInfoHeader);
700 int sn = (int) ((Math.random() * 9 + 1) * 100000); 719 int sn = (int) ((Math.random() * 9 + 1) * 100000);
701 - rpcCameraChannel(deviceSessionCtx,sn); 720 + rpcCameraChannel(deviceSessionCtx, sn);
702 } catch (InvalidArgumentException | SipException | ParseException e) { 721 } catch (InvalidArgumentException | SipException | ParseException e) {
703 throw new RuntimeException(e); 722 throw new RuntimeException(e);
704 } 723 }
705 724
706 - // transportService.getCallbackExecutor().execute(() -> 725 + // transportService.getCallbackExecutor().execute(() ->
707 // processQueueMessage(ctx)); //this callback will execute in Producer worker thread and 726 // processQueueMessage(ctx)); //this callback will execute in Producer worker thread and
708 // hard or blocking work have to be submitted to the separate thread. 727 // hard or blocking work have to be submitted to the separate thread.
709 } 728 }
@@ -735,9 +754,6 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -735,9 +754,6 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
735 // sipSender.transmitRequest(hostAddress, finalResponse); 754 // sipSender.transmitRequest(hostAddress, finalResponse);
736 } 755 }
737 756
738 -  
739 -  
740 -  
741 /** 757 /**
742 * 向超时订阅发送消息 758 * 向超时订阅发送消息
743 * 759 *
@@ -792,10 +808,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -792,10 +808,12 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
792 808
793 String channelId = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.CHANNEL_ID); 809 String channelId = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.CHANNEL_ID);
794 810
795 - switch (VideoMethodEnum.valueOf(methodType)){ 811 + switch (VideoMethodEnum.valueOf(methodType)) {
796 case BYE: 812 case BYE:
797 - SipMessageHeaderDTO messageHeaderDTO = JacksonUtil.convertValue(rpcBody.get(FastIotConstants.ZLMediaBody.MSG_HEADER),SipMessageHeaderDTO.class);  
798 - commanderService.streamByeCmd(devSession,messageHeaderDTO,channelId); 813 + SipMessageHeaderDTO messageHeaderDTO =
  814 + JacksonUtil.convertValue(
  815 + rpcBody.get(FastIotConstants.ZLMediaBody.MSG_HEADER), SipMessageHeaderDTO.class);
  816 + commanderService.streamByeCmd(devSession, messageHeaderDTO, channelId);
799 break; 817 break;
800 case INVITE: 818 case INVITE:
801 JsonNode mediaInform = rpcBody.get(FastIotConstants.ZLMediaBody.MEDIA); 819 JsonNode mediaInform = rpcBody.get(FastIotConstants.ZLMediaBody.MEDIA);
@@ -807,64 +825,81 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -807,64 +825,81 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
807 String stream = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.SSRCINFO_STREAM); 825 String stream = rpcParamVal(rpcBody, FastIotConstants.ZLMediaBody.SSRCINFO_STREAM);
808 826
809 ObjectNode responseJson = JacksonUtil.newObjectNode(); 827 ObjectNode responseJson = JacksonUtil.newObjectNode();
810 - responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM,stream);  
811 - responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_PORT,ssrcPort);  
812 - responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_SSRC,ssrc);  
813 - responseJson.set(FastIotConstants.ZLMediaBody.MEDIA,mediaInform);  
814 - responseJson.put(FastIotConstants.ZLMediaBody.CAMERA_CODE,cameraCode);  
815 - 828 + responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM, stream);
  829 + responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_PORT, ssrcPort);
  830 + responseJson.put(FastIotConstants.ZLMediaBody.SSRCINFO_SSRC, ssrc);
  831 + responseJson.set(FastIotConstants.ZLMediaBody.MEDIA, mediaInform);
  832 + responseJson.put(FastIotConstants.ZLMediaBody.CAMERA_CODE, cameraCode);
816 833
817 SipMessageHeaderDTO sipMessageHeaderDTO = 834 SipMessageHeaderDTO sipMessageHeaderDTO =
818 - SipMessageHeaderDTO.builder()  
819 - .viaTag(TKSipUtils.getNewViaTag())  
820 - .fromTag(TKSipUtils.getNewViaTag())  
821 - .toTag(null)  
822 - .build(); 835 + SipMessageHeaderDTO.builder()
  836 + .viaTag(TKSipUtils.getNewViaTag())
  837 + .fromTag(TKSipUtils.getNewViaTag())
  838 + .toTag(null)
  839 + .build();
823 840
824 commanderService.previewStreamCmd( 841 commanderService.previewStreamCmd(
825 - devSession, sipMessageHeaderDTO, sdpIp, ssrc, ssrcPort, channelId,  
826 - e -> {  
827 - // TODO: 2023/10/13 命令下发失败,需要流媒体处理的业务逻辑  
828 -  
829 -// responseJson.set(FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(e));  
830 - String contentString = JacksonUtil.toString(responseJson);  
831 - log.warn("命令下发【失败】,响应给流媒体的数据【{}】",contentString);  
832 - transportService.process(devSession.getSessionInfo(),  
833 - TransportProtos.ToDeviceRpcResponseMsg.newBuilder()  
834 - .setRequestId(rpcRequest.getRequestId()).setError(e.msg).build(), TransportServiceCallback.EMPTY);  
835 - },  
836 - e -> {  
837 - // TODO: 2023/10/13 命令下发成功,需要流媒体处理的业务逻辑  
838 - transportService.process(devSession.getSessionInfo(), rpcRequest, RpcStatus.SENT, TransportServiceCallback.EMPTY);  
839 -  
840 -  
841 - responseJson.put(FastIotConstants.ZLMediaBody.CALL_ID,e.callId);  
842 - ResponseEvent responseEvent = (ResponseEvent) e.event;  
843 - SIPResponse response = (SIPResponse) responseEvent.getResponse();  
844 - SipMessageHeaderDTO sipMessage =  
845 - SipMessageHeaderDTO.builder()  
846 - .callId(response.getCallIdHeader().getCallId())  
847 - .fromTag(response.getFromTag())  
848 - .toTag(response.getToTag())  
849 - .viaBranch(response.getTopmostViaHeader().getBranch())  
850 - .build();  
851 - responseJson.set(FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(sipMessage));  
852 - String contentString = new String(responseEvent.getResponse().getRawContent());  
853 - responseJson.put(FastIotConstants.ZLMediaBody.MSG_CONTEXT, contentString);  
854 - responseJson.put(FastIotConstants.ZLMediaBody.SESSION_TYPE,SessionTypeEnum.PLAY.name());  
855 - responseJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID,channelId);  
856 - responseJson.put(FastIotConstants.ZLMediaBody.SSRC_CHECK,devSession.isSsrcCheck());  
857 - String responseStr = JacksonUtil.toString(responseJson);  
858 - log.warn("命令下发【成功】,CallId是否一致【{}】,响应给流媒体的数据【{}】",e.callId.equals(response.getCallIdHeader().getCallId()),responseStr);  
859 - TransportProtos.ToDeviceRpcResponseMsg.Builder builder = TransportProtos.ToDeviceRpcResponseMsg.newBuilder();  
860 - builder.setRequestId(rpcRequest.getRequestId()).setPayload(responseStr);  
861 - transportService.process(devSession.getSessionInfo(),  
862 - builder.build(), TransportServiceCallback.EMPTY);  
863 -  
864 - }); 842 + devSession,
  843 + sipMessageHeaderDTO,
  844 + sdpIp,
  845 + ssrc,
  846 + ssrcPort,
  847 + channelId,
  848 + e -> {
  849 + // TODO: 2023/10/13 命令下发失败,需要流媒体处理的业务逻辑
  850 +
  851 + // responseJson.set(FastIotConstants.ZLMediaBody.MSG_HEADER,
  852 + // JacksonUtil.valueToTree(e));
  853 + String contentString = JacksonUtil.toString(responseJson);
  854 + log.warn("命令下发【失败】,响应给流媒体的数据【{}】", contentString);
  855 + transportService.process(
  856 + devSession.getSessionInfo(),
  857 + TransportProtos.ToDeviceRpcResponseMsg.newBuilder()
  858 + .setRequestId(rpcRequest.getRequestId())
  859 + .setError(e.msg)
  860 + .build(),
  861 + TransportServiceCallback.EMPTY);
  862 + },
  863 + e -> {
  864 + // TODO: 2023/10/13 命令下发成功,需要流媒体处理的业务逻辑
  865 + transportService.process(
  866 + devSession.getSessionInfo(),
  867 + rpcRequest,
  868 + RpcStatus.SENT,
  869 + TransportServiceCallback.EMPTY);
  870 +
  871 + responseJson.put(FastIotConstants.ZLMediaBody.CALL_ID, e.callId);
  872 + ResponseEvent responseEvent = (ResponseEvent) e.event;
  873 + SIPResponse response = (SIPResponse) responseEvent.getResponse();
  874 + SipMessageHeaderDTO sipMessage =
  875 + SipMessageHeaderDTO.builder()
  876 + .callId(response.getCallIdHeader().getCallId())
  877 + .fromTag(response.getFromTag())
  878 + .toTag(response.getToTag())
  879 + .viaBranch(response.getTopmostViaHeader().getBranch())
  880 + .build();
  881 + responseJson.set(
  882 + FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(sipMessage));
  883 + String contentString = new String(responseEvent.getResponse().getRawContent());
  884 + responseJson.put(FastIotConstants.ZLMediaBody.MSG_CONTEXT, contentString);
  885 + responseJson.put(
  886 + FastIotConstants.ZLMediaBody.SESSION_TYPE, SessionTypeEnum.PLAY.name());
  887 + responseJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, channelId);
  888 + responseJson.put(FastIotConstants.ZLMediaBody.SSRC_CHECK, devSession.isSsrcCheck());
  889 + String responseStr = JacksonUtil.toString(responseJson);
  890 + log.warn(
  891 + "命令下发【成功】,CallId是否一致【{}】,响应给流媒体的数据【{}】",
  892 + e.callId.equals(response.getCallIdHeader().getCallId()),
  893 + responseStr);
  894 + TransportProtos.ToDeviceRpcResponseMsg.Builder builder =
  895 + TransportProtos.ToDeviceRpcResponseMsg.newBuilder();
  896 + builder.setRequestId(rpcRequest.getRequestId()).setPayload(responseStr);
  897 + transportService.process(
  898 + devSession.getSessionInfo(), builder.build(), TransportServiceCallback.EMPTY);
  899 + });
865 break; 900 break;
866 case MESSAGE: 901 case MESSAGE:
867 - toDeviceRpcMessage(devSession,channelId,rpcBody); 902 + toDeviceRpcMessage(devSession, channelId, rpcBody);
868 break; 903 break;
869 } 904 }
870 } catch (InvalidArgumentException | SipException | ParseException e) { 905 } catch (InvalidArgumentException | SipException | ParseException e) {
@@ -873,47 +908,54 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -873,47 +908,54 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
873 } 908 }
874 } 909 }
875 910
876 - private void toDeviceRpcMessage(GbtDeviceSessionCtx devSession,String channelId,JsonNode rpcBody) throws InvalidArgumentException, ParseException, SipException { 911 + private void toDeviceRpcMessage(
  912 + GbtDeviceSessionCtx devSession, String channelId, JsonNode rpcBody)
  913 + throws InvalidArgumentException, ParseException, SipException {
877 SipMessageHeaderDTO controlHeaderDTO = 914 SipMessageHeaderDTO controlHeaderDTO =
878 - SipMessageHeaderDTO.builder()  
879 - .viaTag(TKSipUtils.getNewViaTag())  
880 - .fromTag(TKSipUtils.getNewViaTag())  
881 - .toTag(null)  
882 - .build(); 915 + SipMessageHeaderDTO.builder()
  916 + .viaTag(TKSipUtils.getNewViaTag())
  917 + .fromTag(TKSipUtils.getNewViaTag())
  918 + .toTag(null)
  919 + .build();
883 String msgType = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_TYPE).asText(); 920 String msgType = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_TYPE).asText();
884 - switch (VideoXmlEnum.valueOf(msgType)){ 921 + switch (VideoXmlEnum.valueOf(msgType)) {
885 case Control: 922 case Control:
886 - PTZCmdDTO ptzCmdDTO = JacksonUtil.convertValue(rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT),PTZCmdDTO.class);  
887 - commanderService.controlPtzCmd(channelId,devSession,controlHeaderDTO,ptzCmdDTO); 923 + PTZCmdDTO ptzCmdDTO =
  924 + JacksonUtil.convertValue(
  925 + rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT), PTZCmdDTO.class);
  926 + commanderService.controlPtzCmd(channelId, devSession, controlHeaderDTO, ptzCmdDTO);
888 break; 927 break;
889 case Query: 928 case Query:
890 int sn = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT).intValue(); 929 int sn = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT).intValue();
891 - rpcCameraChannel(devSession,sn); 930 + rpcCameraChannel(devSession, sn);
892 } 931 }
893 } 932 }
894 933
895 /** 934 /**
896 * 查询设备通道信息 935 * 查询设备通道信息
  936 + *
897 * @throws InvalidArgumentException 937 * @throws InvalidArgumentException
898 * @throws SipException 938 * @throws SipException
899 * @throws ParseException 939 * @throws ParseException
900 */ 940 */
901 - private void rpcCameraChannel(GbtDeviceSessionCtx deviceSessionCtx,int sn) throws InvalidArgumentException, SipException, ParseException { 941 + private void rpcCameraChannel(GbtDeviceSessionCtx deviceSessionCtx, int sn)
  942 + throws InvalidArgumentException, SipException, ParseException {
902 SipMessageHeaderDTO catalogHeader = 943 SipMessageHeaderDTO catalogHeader =
903 - SipMessageHeaderDTO.builder()  
904 - .viaTag(TKSipUtils.getNewViaTag())  
905 - .fromTag(TKSipUtils.getNewFromTag())  
906 - .build(); 944 + SipMessageHeaderDTO.builder()
  945 + .viaTag(TKSipUtils.getNewViaTag())
  946 + .fromTag(TKSipUtils.getNewFromTag())
  947 + .build();
907 commanderService.queryCatalog( 948 commanderService.queryCatalog(
908 - deviceSessionCtx,  
909 - catalogHeader,  
910 - sn,  
911 - ev -> {  
912 - String errorMsg = String.format("同步通道失败,错误码: %s, %s", ev.statusCode, ev.msg);  
913 - // catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(),  
914 - // errorMsg);  
915 - }); 949 + deviceSessionCtx,
  950 + catalogHeader,
  951 + sn,
  952 + ev -> {
  953 + String errorMsg = String.format("同步通道失败,错误码: %s, %s", ev.statusCode, ev.msg);
  954 + // catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(),
  955 + // errorMsg);
  956 + });
916 } 957 }
  958 +
917 private String rpcParamVal(JsonNode rpcBody, String key) { 959 private String rpcParamVal(JsonNode rpcBody, String key) {
918 if (rpcBody.has(key)) { 960 if (rpcBody.has(key)) {
919 return rpcBody.get(key).asText(); 961 return rpcBody.get(key).asText();
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/SIPProvider.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/SIPProvider.java
1 -package org.thingsboard.server.transport; 1 +package org.thingsboard.server.transport.gbt28181.sip.processor;
2 2
3 import javax.sip.SipListener; 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 import gov.nist.javax.sip.message.SIPRequest; 3 import gov.nist.javax.sip.message.SIPRequest;
4 import gov.nist.javax.sip.message.SIPResponse; 4 import gov.nist.javax.sip.message.SIPResponse;
@@ -20,7 +20,7 @@ import org.dom4j.DocumentException; @@ -20,7 +20,7 @@ import org.dom4j.DocumentException;
20 import org.dom4j.Element; 20 import org.dom4j.Element;
21 import org.dom4j.io.SAXReader; 21 import org.dom4j.io.SAXReader;
22 import org.springframework.beans.factory.annotation.Autowired; 22 import org.springframework.beans.factory.annotation.Autowired;
23 -import org.thingsboard.server.transport.SIPSender; 23 +import org.thingsboard.server.transport.cmd.SIPSender;
24 import org.thingsboard.server.transport.util.TKSipUtils; 24 import org.thingsboard.server.transport.util.TKSipUtils;
25 25
26 /** 处理接收IPCamera发来的SIP协议请求消息 */ 26 /** 处理接收IPCamera发来的SIP协议请求消息 */
common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/gbt28181/sip/processor/TimeoutProcessorImpl.java renamed from common/transport/gbt28181/src/main/java/org/thingsboard/server/transport/process/timeout/TimeoutProcessorImpl.java
1 -package org.thingsboard.server.transport.process.timeout; 1 +package org.thingsboard.server.transport.gbt28181.sip.processor;
2 2
3 import javax.sip.TimeoutEvent; 3 import javax.sip.TimeoutEvent;
4 import javax.sip.header.CallIdHeader; 4 import javax.sip.header.CallIdHeader;
@@ -8,8 +8,6 @@ import org.springframework.beans.factory.InitializingBean; @@ -8,8 +8,6 @@ import org.springframework.beans.factory.InitializingBean;
8 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
9 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 9 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
10 import org.springframework.stereotype.Component; 10 import org.springframework.stereotype.Component;
11 -import org.thingsboard.server.transport.gbt28181.ITimeoutProcessor;  
12 -import org.thingsboard.server.transport.SIPProcessorObserver;  
13 import org.thingsboard.server.transport.gbt28181.SipSubscribe; 11 import org.thingsboard.server.transport.gbt28181.SipSubscribe;
14 12
15 @Component 13 @Component
  1 +package org.thingsboard.server.transport.gbt28181.zlm;
  2 +
  3 +import com.google.protobuf.ByteString;
  4 +import java.net.InetAddress;
  5 +import java.net.UnknownHostException;
  6 +import java.util.List;
  7 +import lombok.Getter;
  8 +import lombok.RequiredArgsConstructor;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.beans.factory.annotation.Value;
  11 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  12 +import org.springframework.boot.context.event.ApplicationReadyEvent;
  13 +import org.springframework.context.event.EventListener;
  14 +import org.springframework.core.annotation.Order;
  15 +import org.springframework.stereotype.Component;
  16 +import org.thingsboard.common.util.JacksonUtil;
  17 +import org.thingsboard.server.common.data.StringUtils;
  18 +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
  19 +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils;
  20 +import org.thingsboard.server.common.data.yunteng.utils.DataUtils;
  21 +import org.thingsboard.server.common.transport.TransportService;
  22 +import org.thingsboard.server.common.transport.util.DataDecodingEncodingService;
  23 +import org.thingsboard.server.gen.transport.TransportProtos;
  24 +import org.thingsboard.server.transport.config.MediaConfig;
  25 +import org.thingsboard.server.transport.config.SipConfig;
  26 +
  27 +@Component()
  28 +@Slf4j
  29 +@RequiredArgsConstructor
  30 +@ConditionalOnExpression(
  31 + "'${service.type:null}'=='tb-transport' || ('${service.type:null}'=='monolith' && '${transport.api_enabled:true}'=='true' && '${transport.gbt28181.enabled}'=='true')")
  32 +public class ZLMediaKitStateRunner {
  33 + private final MediaConfig mediaConfig;
  34 + private final SipConfig sipConfig;
  35 + private final DataDecodingEncodingService encodingService;
  36 + private final CacheUtils cacheUtils;
  37 +
  38 + @Value("${transport.gbt28181.media.defaultStateCheckIntervalInSec}")
  39 + @Getter
  40 + private int defaultStateCheckIntervalInSec;
  41 +
  42 + private final TransportService transportService;
  43 +
  44 + @EventListener(ApplicationReadyEvent.class)
  45 + @Order(value = 3)
  46 + public void init(ApplicationReadyEvent applicationReadyEvent) throws UnknownHostException {
  47 + TransportProtos.Gbt28181MediaServerMsg.Builder msgBuilder =
  48 + TransportProtos.Gbt28181MediaServerMsg.newBuilder();
  49 + cacheUtils.put(
  50 + FastIotConstants.CacheSipKey.TK_SIP_CACHE_NAME,
  51 + mediaConfig.getMediaServerId(),
  52 + sipConfig.getDomain());
  53 + if (StringUtils.isEmpty(mediaConfig.getHookIp())) {
  54 + mediaConfig.setHookIp(sipConfig.getIp().split(",")[0]);
  55 + }
  56 + if (StringUtils.isEmpty(mediaConfig.getStreamIp())) {
  57 + mediaConfig.setStreamIp(mediaConfig.getIp());
  58 + }
  59 + String sdpIp = mediaConfig.getSdpIp();
  60 + if (StringUtils.isEmpty(sdpIp)) {
  61 + sdpIp = mediaConfig.getIp();
  62 + } else if (!DataUtils.isIPAddress(sdpIp)) {
  63 + sdpIp = InetAddress.getByName(sdpIp).getHostAddress();
  64 + }
  65 + mediaConfig.setSdpIp(sdpIp);
  66 + byte[] mediaMsgBytes = encodingService.encode(JacksonUtil.valueToTree(mediaConfig));
  67 + msgBuilder.setProfile(ByteString.copyFrom(mediaMsgBytes));
  68 + // 从数据库获取所有的流媒体信息
  69 + List<TransportProtos.Gbt28181MediaServerMsg> dtoList =
  70 + transportService.freshGtb28181Media(msgBuilder.build());
  71 + }
  72 +}
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,9 +13,7 @@ import lombok.Getter;
13 import lombok.Setter; 13 import lombok.Setter;
14 import lombok.extern.slf4j.Slf4j; 14 import lombok.extern.slf4j.Slf4j;
15 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext; 15 import org.thingsboard.server.common.transport.session.DeviceAwareSessionContext;
16 -import org.thingsboard.server.transport.GbtTransportContext;  
17 -  
18 -import javax.sip.RequestEvent; 16 +import org.thingsboard.server.transport.gbt28181.session.GbtTransportContext;
19 17
20 /** 18 /**
21 * @author Andrew Shvayka 19 * @author Andrew Shvayka
@@ -10,10 +10,10 @@ import javax.sip.SipFactory; @@ -10,10 +10,10 @@ import javax.sip.SipFactory;
10 import javax.sip.header.UserAgentHeader; 10 import javax.sip.header.UserAgentHeader;
11 import org.apache.commons.lang3.RandomStringUtils; 11 import org.apache.commons.lang3.RandomStringUtils;
12 import org.springframework.util.ObjectUtils; 12 import org.springframework.util.ObjectUtils;
13 -import org.thingsboard.server.common.data.yunteng.config.media.ThingsKitVersionConfig;  
14 import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO; 13 import org.thingsboard.server.common.data.yunteng.dto.sip.PTZCmdDTO;
15 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; 14 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO;
16 -import org.thingsboard.server.transport.info.RemoteAddressInfo; 15 +import org.thingsboard.server.transport.config.ThingsKitVersionConfig;
  16 +import org.thingsboard.server.transport.gbt28181.auth.RemoteAddressInfo;
17 17
18 public class TKSipUtils { 18 public class TKSipUtils {
19 public static String getNewMessageViaBranchTag() { 19 public static String getNewMessageViaBranchTag() {
@@ -55,14 +55,14 @@ public class TKSipUtils { @@ -55,14 +55,14 @@ public class TKSipUtils {
55 builder.append(strTmp, 0, 2); 55 builder.append(strTmp, 0, 2);
56 strTmp = String.format("%X", combineCode2); 56 strTmp = String.format("%X", combineCode2);
57 builder.append(strTmp, 0, 1).append("0"); 57 builder.append(strTmp, 0, 1).append("0");
58 - //计算校验码  
59 - int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100; 58 + // 计算校验码
  59 + int checkCode =
  60 + (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;
60 strTmp = String.format("%02X", checkCode); 61 strTmp = String.format("%02X", checkCode);
61 builder.append(strTmp, 0, 2); 62 builder.append(strTmp, 0, 2);
62 return builder.toString(); 63 return builder.toString();
63 } 64 }
64 65
65 -  
66 public static UserAgentHeader createUserAgentHeader(ThingsKitVersionConfig config) 66 public static UserAgentHeader createUserAgentHeader(ThingsKitVersionConfig config)
67 throws PeerUnavailableException, ParseException { 67 throws PeerUnavailableException, ParseException {
68 List<String> agentParam = new ArrayList<>(); 68 List<String> agentParam = new ArrayList<>();
1 /** 1 /**
2 * Copyright © 2016-2022 The Thingsboard Authors 2 * Copyright © 2016-2022 The Thingsboard Authors
3 * 3 *
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at 4 + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5 + * except in compliance with the License. You may obtain a copy of the License at
7 * 6 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 7 + * <p>http://www.apache.org/licenses/LICENSE-2.0
9 * 8 *
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and 9 + * <p>Unless required by applicable law or agreed to in writing, software distributed under the
  10 + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  11 + * express or implied. See the License for the specific language governing permissions and
14 * limitations under the License. 12 * limitations under the License.
15 */ 13 */
16 package org.thingsboard.server.common.transport; 14 package org.thingsboard.server.common.transport;
17 15
  16 +import java.util.List;
  17 +import java.util.concurrent.ExecutorService;
  18 +import java.util.concurrent.atomic.AtomicInteger;
18 import org.thingsboard.server.common.data.DeviceProfile; 19 import org.thingsboard.server.common.data.DeviceProfile;
19 import org.thingsboard.server.common.data.DeviceTransportType; 20 import org.thingsboard.server.common.data.DeviceTransportType;
20 import org.thingsboard.server.common.data.rpc.RpcStatus; 21 import org.thingsboard.server.common.data.rpc.RpcStatus;
@@ -40,10 +41,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRespon @@ -40,10 +41,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.GetSnmpDevicesRespon
40 import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg; 41 import org.thingsboard.server.gen.transport.TransportProtos.LwM2MRequestMsg;
41 import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg; 42 import org.thingsboard.server.gen.transport.TransportProtos.LwM2MResponseMsg;
42 import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; 43 import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg;
43 -import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;  
44 import org.thingsboard.server.gen.transport.TransportProtos.PostEventMsg; 44 import org.thingsboard.server.gen.transport.TransportProtos.PostEventMsg;
  45 +import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg;
45 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; 46 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
46 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; 47 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
  48 +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto;
47 import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg; 49 import org.thingsboard.server.gen.transport.TransportProtos.SessionEventMsg;
48 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; 50 import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto;
49 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg; 51 import org.thingsboard.server.gen.transport.TransportProtos.SubscribeToAttributeUpdatesMsg;
@@ -57,104 +59,140 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre @@ -57,104 +59,140 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre
57 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg; 59 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg;
58 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; 60 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
59 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; 61 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
60 -import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto;  
61 62
62 -import java.util.List;  
63 -import java.util.concurrent.ExecutorService;  
64 -import java.util.concurrent.atomic.AtomicInteger;  
65 -  
66 -/**  
67 - * Created by ashvayka on 04.10.18.  
68 - */ 63 +/** Created by ashvayka on 04.10.18. */
69 public interface TransportService { 64 public interface TransportService {
70 65
71 - GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg);  
72 -  
73 - GetResourceResponseMsg getResource(GetResourceRequestMsg msg);  
74 -  
75 - GetSnmpDevicesResponseMsg getSnmpDevicesIds(GetSnmpDevicesRequestMsg requestMsg);  
76 -  
77 - GetDeviceResponseMsg getDevice(GetDeviceRequestMsg requestMsg);  
78 -  
79 - GetDeviceCredentialsResponseMsg getDeviceCredentials(GetDeviceCredentialsRequestMsg requestMsg); 66 + GetEntityProfileResponseMsg getEntityProfile(GetEntityProfileRequestMsg msg);
80 67
  68 + GetResourceResponseMsg getResource(GetResourceRequestMsg msg);
81 69
  70 + GetSnmpDevicesResponseMsg getSnmpDevicesIds(GetSnmpDevicesRequestMsg requestMsg);
82 71
83 - void process(DeviceTransportType transportType, ValidateDeviceTokenRequestMsg msg,  
84 - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); 72 + GetDeviceResponseMsg getDevice(GetDeviceRequestMsg requestMsg);
85 73
86 - void process(DeviceTransportType transportType, ValidateBasicMqttCredRequestMsg msg,  
87 - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); 74 + GetDeviceCredentialsResponseMsg getDeviceCredentials(GetDeviceCredentialsRequestMsg requestMsg);
88 75
89 - void process(DeviceTransportType transportType, ValidateDeviceX509CertRequestMsg msg,  
90 - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); 76 + void process(
  77 + DeviceTransportType transportType,
  78 + ValidateDeviceTokenRequestMsg msg,
  79 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
91 80
92 - void process(ValidateDeviceLwM2MCredentialsRequestMsg msg,  
93 - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback); 81 + void process(
  82 + DeviceTransportType transportType,
  83 + ValidateBasicMqttCredRequestMsg msg,
  84 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
94 85
95 - void process(GetOrCreateDeviceFromGatewayRequestMsg msg,  
96 - TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback); 86 + void process(
  87 + DeviceTransportType transportType,
  88 + ValidateDeviceX509CertRequestMsg msg,
  89 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
97 90
98 - void process(ProvisionDeviceRequestMsg msg,  
99 - TransportServiceCallback<ProvisionDeviceResponseMsg> callback); 91 + void process(
  92 + ValidateDeviceLwM2MCredentialsRequestMsg msg,
  93 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback);
100 94
101 - void onProfileUpdate(DeviceProfile deviceProfile); 95 + void process(
  96 + GetOrCreateDeviceFromGatewayRequestMsg msg,
  97 + TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback);
102 98
103 - void process(LwM2MRequestMsg msg,  
104 - TransportServiceCallback<LwM2MResponseMsg> callback); 99 + void process(
  100 + ProvisionDeviceRequestMsg msg, TransportServiceCallback<ProvisionDeviceResponseMsg> callback);
105 101
106 - void process(SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback<Void> callback); 102 + void onProfileUpdate(DeviceProfile deviceProfile);
107 103
108 - void process(SessionInfoProto sessionInfo, PostTelemetryMsg msg, TransportServiceCallback<Void> callback); 104 + void process(LwM2MRequestMsg msg, TransportServiceCallback<LwM2MResponseMsg> callback);
109 105
110 - void process(SessionInfoProto sessionInfo, PostAttributeMsg msg, TransportServiceCallback<Void> callback); 106 + void process(
  107 + SessionInfoProto sessionInfo, SessionEventMsg msg, TransportServiceCallback<Void> callback);
111 108
  109 + void process(
  110 + SessionInfoProto sessionInfo, PostTelemetryMsg msg, TransportServiceCallback<Void> callback);
112 111
113 - void process(SessionInfoProto sessionInfo, GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback); 112 + void process(
  113 + SessionInfoProto sessionInfo, PostAttributeMsg msg, TransportServiceCallback<Void> callback);
114 114
115 - void process(SessionInfoProto sessionInfo, SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback); 115 + void process(
  116 + SessionInfoProto sessionInfo,
  117 + GetAttributeRequestMsg msg,
  118 + TransportServiceCallback<Void> callback);
116 119
117 - void process(SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback); 120 + void process(
  121 + SessionInfoProto sessionInfo,
  122 + SubscribeToAttributeUpdatesMsg msg,
  123 + TransportServiceCallback<Void> callback);
118 124
119 - void process(SessionInfoProto sessionInfo, ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback); 125 + void process(
  126 + SessionInfoProto sessionInfo, SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback);
120 127
121 - void process(SessionInfoProto sessionInfo, ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback); 128 + void process(
  129 + SessionInfoProto sessionInfo,
  130 + ToDeviceRpcResponseMsg msg,
  131 + TransportServiceCallback<Void> callback);
122 132
123 - void process(SessionInfoProto sessionInfo, ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback); 133 + void process(
  134 + SessionInfoProto sessionInfo,
  135 + ToServerRpcRequestMsg msg,
  136 + TransportServiceCallback<Void> callback);
124 137
125 - void process(SessionInfoProto sessionInfo, SubscriptionInfoProto msg, TransportServiceCallback<Void> callback); 138 + void process(
  139 + SessionInfoProto sessionInfo,
  140 + ToDeviceRpcRequestMsg msg,
  141 + RpcStatus rpcStatus,
  142 + TransportServiceCallback<Void> callback);
126 143
127 - void process(SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> callback); 144 + void process(
  145 + SessionInfoProto sessionInfo,
  146 + SubscriptionInfoProto msg,
  147 + TransportServiceCallback<Void> callback);
128 148
129 - void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback); 149 + void process(
  150 + SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> callback);
130 151
131 - void process(SessionInfoProto sessionInfoProto, GetOtaPackageRequestMsg msg, TransportServiceCallback<GetOtaPackageResponseMsg> callback); 152 + void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback);
132 153
133 - SessionMetaData registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener); 154 + void process(
  155 + SessionInfoProto sessionInfoProto,
  156 + GetOtaPackageRequestMsg msg,
  157 + TransportServiceCallback<GetOtaPackageResponseMsg> callback);
134 158
135 - SessionMetaData registerSyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout); 159 + SessionMetaData registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener);
136 160
137 - void reportActivity(SessionInfoProto sessionInfo); 161 + SessionMetaData registerSyncSession(
  162 + SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout);
138 163
139 - void deregisterSession(SessionInfoProto sessionInfo); 164 + void reportActivity(SessionInfoProto sessionInfo);
140 165
141 - void log(SessionInfoProto sessionInfo, String msg); 166 + void deregisterSession(SessionInfoProto sessionInfo);
142 167
143 - void notifyAboutUplink(SessionInfoProto sessionInfo, TransportProtos.UplinkNotificationMsg build, TransportServiceCallback<Void> empty); 168 + void log(SessionInfoProto sessionInfo, String msg);
144 169
145 - ExecutorService getCallbackExecutor(); 170 + void notifyAboutUplink(
  171 + SessionInfoProto sessionInfo,
  172 + TransportProtos.UplinkNotificationMsg build,
  173 + TransportServiceCallback<Void> empty);
146 174
147 - boolean hasSession(SessionInfoProto sessionInfo); 175 + ExecutorService getCallbackExecutor();
148 176
149 - void createGaugeStats(String openConnections, AtomicInteger connectionsCounter); 177 + boolean hasSession(SessionInfoProto sessionInfo);
150 178
  179 + void createGaugeStats(String openConnections, AtomicInteger connectionsCounter);
151 180
  181 + // Thingskit function:begin
  182 + List<ScriptProto> getScripts(ScriptProto msg);
152 183
  184 + void process(
  185 + SessionInfoProto sessionInfo,
  186 + PostEventMsg msg,
  187 + TransportServiceCallback<Void> callback,
  188 + String topicName);
153 189
  190 + void process(
  191 + SessionInfoProto sessionInfo,
  192 + TransportProtos.Gbt28181RequestMsg msg,
  193 + TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback);
154 194
155 - //Thingskit function:begin  
156 - List<ScriptProto> getScripts(ScriptProto msg);  
157 - void process(SessionInfoProto sessionInfo, PostEventMsg msg, TransportServiceCallback<Void> callback,String topicName);  
158 - void process(SessionInfoProto sessionInfo, TransportProtos.Gbt28181RequestMsg msg, TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback);  
159 - //Thingskit function:end 195 + List<TransportProtos.Gbt28181MediaServerMsg> freshGtb28181Media(
  196 + TransportProtos.Gbt28181MediaServerMsg msg);
  197 + // Thingskit function:end
160 } 198 }
1 /** 1 /**
2 * Copyright © 2016-2022 The Thingsboard Authors 2 * Copyright © 2016-2022 The Thingsboard Authors
3 * 3 *
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at 4 + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5 + * except in compliance with the License. You may obtain a copy of the License at
7 * 6 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 7 + * <p>http://www.apache.org/licenses/LICENSE-2.0
9 * 8 *
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and 9 + * <p>Unless required by applicable law or agreed to in writing, software distributed under the
  10 + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  11 + * express or implied. See the License for the specific language governing permissions and
14 * limitations under the License. 12 * limitations under the License.
15 */ 13 */
16 package org.thingsboard.server.common.transport.service; 14 package org.thingsboard.server.common.transport.service;
17 15
  16 +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.EVENT_IDENTIFIER;
  17 +
18 import com.google.common.util.concurrent.Futures; 18 import com.google.common.util.concurrent.Futures;
19 import com.google.common.util.concurrent.ListenableFuture; 19 import com.google.common.util.concurrent.ListenableFuture;
20 import com.google.common.util.concurrent.MoreExecutors; 20 import com.google.common.util.concurrent.MoreExecutors;
21 import com.google.gson.Gson; 21 import com.google.gson.Gson;
22 import com.google.gson.JsonObject; 22 import com.google.gson.JsonObject;
23 import com.google.protobuf.ByteString; 23 import com.google.protobuf.ByteString;
  24 +import java.util.Collections;
  25 +import java.util.HashSet;
  26 +import java.util.LinkedHashMap;
  27 +import java.util.List;
  28 +import java.util.Map;
  29 +import java.util.Optional;
  30 +import java.util.Random;
  31 +import java.util.Set;
  32 +import java.util.UUID;
  33 +import java.util.concurrent.*;
  34 +import java.util.concurrent.atomic.AtomicInteger;
  35 +import java.util.stream.Collectors;
  36 +import javax.annotation.PostConstruct;
  37 +import javax.annotation.PreDestroy;
24 import lombok.Getter; 38 import lombok.Getter;
25 import lombok.extern.slf4j.Slf4j; 39 import lombok.extern.slf4j.Slf4j;
26 import org.springframework.beans.factory.annotation.Value; 40 import org.springframework.beans.factory.annotation.Value;
27 import org.springframework.context.ApplicationEventPublisher; 41 import org.springframework.context.ApplicationEventPublisher;
  42 +import org.springframework.core.annotation.Order;
28 import org.springframework.scheduling.annotation.Scheduled; 43 import org.springframework.scheduling.annotation.Scheduled;
29 import org.springframework.stereotype.Service; 44 import org.springframework.stereotype.Service;
30 import org.thingsboard.common.util.ThingsBoardExecutors; 45 import org.thingsboard.common.util.ThingsBoardExecutors;
@@ -79,13 +94,13 @@ import org.thingsboard.server.common.transport.yunteng.ScriptUpdatedEvent; @@ -79,13 +94,13 @@ import org.thingsboard.server.common.transport.yunteng.ScriptUpdatedEvent;
79 import org.thingsboard.server.gen.transport.TransportProtos; 94 import org.thingsboard.server.gen.transport.TransportProtos;
80 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg; 95 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
81 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg; 96 import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceResponseMsg;
  97 +import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto;
82 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg; 98 import org.thingsboard.server.gen.transport.TransportProtos.ToCoreMsg;
83 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg; 99 import org.thingsboard.server.gen.transport.TransportProtos.ToRuleEngineMsg;
84 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg; 100 import org.thingsboard.server.gen.transport.TransportProtos.ToTransportMsg;
85 import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg; 101 import org.thingsboard.server.gen.transport.TransportProtos.TransportApiRequestMsg;
86 import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg; 102 import org.thingsboard.server.gen.transport.TransportProtos.TransportApiResponseMsg;
87 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg; 103 import org.thingsboard.server.gen.transport.TransportProtos.TransportToDeviceActorMsg;
88 -import org.thingsboard.server.gen.transport.TransportProtos.ScriptProto;  
89 import org.thingsboard.server.queue.TbQueueCallback; 104 import org.thingsboard.server.queue.TbQueueCallback;
90 import org.thingsboard.server.queue.TbQueueConsumer; 105 import org.thingsboard.server.queue.TbQueueConsumer;
91 import org.thingsboard.server.queue.TbQueueMsgMetadata; 106 import org.thingsboard.server.queue.TbQueueMsgMetadata;
@@ -102,1204 +117,1604 @@ import org.thingsboard.server.queue.usagestats.TbApiUsageClient; @@ -102,1204 +117,1604 @@ import org.thingsboard.server.queue.usagestats.TbApiUsageClient;
102 import org.thingsboard.server.queue.util.AfterStartUp; 117 import org.thingsboard.server.queue.util.AfterStartUp;
103 import org.thingsboard.server.queue.util.TbTransportComponent; 118 import org.thingsboard.server.queue.util.TbTransportComponent;
104 119
105 -import javax.annotation.PostConstruct;  
106 -import javax.annotation.PreDestroy;  
107 -import java.util.Collections;  
108 -import java.util.HashSet;  
109 -import java.util.LinkedHashMap;  
110 -import java.util.List;  
111 -import java.util.Map;  
112 -import java.util.Optional;  
113 -import java.util.Random;  
114 -import java.util.Set;  
115 -import java.util.UUID;  
116 -import java.util.concurrent.*;  
117 -import java.util.concurrent.atomic.AtomicInteger;  
118 -import java.util.stream.Collectors;  
119 -  
120 -import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.EVENT_IDENTIFIER;  
121 -  
122 -/**  
123 - * Created by ashvayka on 17.10.18.  
124 - */ 120 +/** Created by ashvayka on 17.10.18. */
125 @Slf4j 121 @Slf4j
126 @Service 122 @Service
  123 +@Order(value = 3)
127 @TbTransportComponent 124 @TbTransportComponent
128 public class DefaultTransportService implements TransportService { 125 public class DefaultTransportService implements TransportService {
129 126
130 - public static final String OVERWRITE_ACTIVITY_TIME = "overwriteActivityTime";  
131 - public static final String SESSION_EXPIRED_MESSAGE = "Session has expired due to last activity time!";  
132 - public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_OPEN = getSessionEventMsg(TransportProtos.SessionEvent.OPEN);  
133 - public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_CLOSED = getSessionEventMsg(TransportProtos.SessionEvent.CLOSED);  
134 - public static final TransportProtos.SessionCloseNotificationProto SESSION_CLOSE_NOTIFICATION_PROTO = TransportProtos.SessionCloseNotificationProto.newBuilder()  
135 - .setMessage(SESSION_EXPIRED_MESSAGE).build();  
136 - public static final TransportProtos.SubscribeToAttributeUpdatesMsg SUBSCRIBE_TO_ATTRIBUTE_UPDATES_ASYNC_MSG = TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder()  
137 - .setSessionType(TransportProtos.SessionType.ASYNC).build();  
138 - public static final TransportProtos.SubscribeToRPCMsg SUBSCRIBE_TO_RPC_ASYNC_MSG = TransportProtos.SubscribeToRPCMsg.newBuilder()  
139 - .setSessionType(TransportProtos.SessionType.ASYNC).build();  
140 -  
141 - private final AtomicInteger atomicTs = new AtomicInteger(0);  
142 -  
143 - @Value("${transport.log.enabled:true}")  
144 - private boolean logEnabled;  
145 - @Value("${transport.log.max_length:1024}")  
146 - private int logMaxLength;  
147 - @Value("${transport.sessions.inactivity_timeout}")  
148 - private long sessionInactivityTimeout;  
149 - @Value("${transport.sessions.report_timeout}")  
150 - private long sessionReportTimeout;  
151 - @Value("${transport.client_side_rpc.timeout:60000}")  
152 - private long clientSideRpcTimeout;  
153 - @Value("${queue.transport.poll_interval}")  
154 - private int notificationsPollDuration;  
155 - @Value("${transport.stats.enabled:false}")  
156 - private boolean statsEnabled;  
157 -  
158 - private final Map<String, Number> statsMap = new LinkedHashMap<>();  
159 -  
160 - private final Gson gson = new Gson();  
161 - private final TbTransportQueueFactory queueProvider;  
162 - private final TbQueueProducerProvider producerProvider;  
163 - private final PartitionService partitionService;  
164 - private final TbServiceInfoProvider serviceInfoProvider;  
165 - private final StatsFactory statsFactory;  
166 - private final TransportDeviceProfileCache deviceProfileCache;  
167 - private final TransportTenantProfileCache tenantProfileCache;  
168 - private final TbApiUsageClient apiUsageClient;  
169 - private final TransportRateLimitService rateLimitService;  
170 - private final DataDecodingEncodingService dataDecodingEncodingService;  
171 - private final SchedulerComponent scheduler;  
172 - private final ApplicationEventPublisher eventPublisher;  
173 - private final TransportResourceCache transportResourceCache;  
174 -  
175 -  
176 - protected TbQueueRequestTemplate<TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>> transportApiRequestTemplate;  
177 - protected TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> ruleEngineMsgProducer;  
178 - protected TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> tbCoreMsgProducer;  
179 - protected TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> transportNotificationsConsumer;  
180 -  
181 - protected MessagesStats ruleEngineProducerStats;  
182 - protected MessagesStats tbCoreProducerStats;  
183 - protected MessagesStats transportApiStats;  
184 -  
185 - protected ExecutorService transportCallbackExecutor;  
186 - private ExecutorService mainConsumerExecutor;  
187 -  
188 - private final ConcurrentMap<UUID, SessionMetaData> sessions = new ConcurrentHashMap<>();  
189 - private final ConcurrentMap<UUID, SessionActivityData> sessionsActivity = new ConcurrentHashMap<>();  
190 - private final Map<String, RpcRequestMetadata> toServerRpcPendingMap = new ConcurrentHashMap<>();  
191 -  
192 - @Getter  
193 - /**TCP协议的鉴权脚本*/  
194 - private final ConcurrentSkipListSet<UUID> authScripts = new ConcurrentSkipListSet<>();  
195 - private volatile boolean stopped = false;  
196 -  
197 - public DefaultTransportService(TbServiceInfoProvider serviceInfoProvider,  
198 - TbTransportQueueFactory queueProvider,  
199 - TbQueueProducerProvider producerProvider,  
200 - PartitionService partitionService,  
201 - StatsFactory statsFactory,  
202 - TransportDeviceProfileCache deviceProfileCache,  
203 - TransportTenantProfileCache tenantProfileCache,  
204 - TbApiUsageClient apiUsageClient, TransportRateLimitService rateLimitService,  
205 - DataDecodingEncodingService dataDecodingEncodingService, SchedulerComponent scheduler, TransportResourceCache transportResourceCache,  
206 - ApplicationEventPublisher eventPublisher) {  
207 - this.serviceInfoProvider = serviceInfoProvider;  
208 - this.queueProvider = queueProvider;  
209 - this.producerProvider = producerProvider;  
210 - this.partitionService = partitionService;  
211 - this.statsFactory = statsFactory;  
212 - this.deviceProfileCache = deviceProfileCache;  
213 - this.tenantProfileCache = tenantProfileCache;  
214 - this.apiUsageClient = apiUsageClient;  
215 - this.rateLimitService = rateLimitService;  
216 - this.dataDecodingEncodingService = dataDecodingEncodingService;  
217 - this.scheduler = scheduler;  
218 - this.transportResourceCache = transportResourceCache;  
219 - this.eventPublisher = eventPublisher;  
220 - }  
221 -  
222 - @PostConstruct  
223 - public void init() {  
224 - this.ruleEngineProducerStats = statsFactory.createMessagesStats(StatsType.RULE_ENGINE.getName() + ".producer");  
225 - this.tbCoreProducerStats = statsFactory.createMessagesStats(StatsType.CORE.getName() + ".producer");  
226 - this.transportApiStats = statsFactory.createMessagesStats(StatsType.TRANSPORT.getName() + ".producer");  
227 - this.transportCallbackExecutor = ThingsBoardExecutors.newWorkStealingPool(20, getClass());  
228 - this.scheduler.scheduleAtFixedRate(this::checkInactivityAndReportActivity, new Random().nextInt((int) sessionReportTimeout), sessionReportTimeout, TimeUnit.MILLISECONDS);  
229 - this.scheduler.scheduleAtFixedRate(this::invalidateRateLimits, new Random().nextInt((int) sessionReportTimeout), sessionReportTimeout, TimeUnit.MILLISECONDS);  
230 - transportApiRequestTemplate = queueProvider.createTransportApiRequestTemplate();  
231 - transportApiRequestTemplate.setMessagesStats(transportApiStats);  
232 - ruleEngineMsgProducer = producerProvider.getRuleEngineMsgProducer();  
233 - tbCoreMsgProducer = producerProvider.getTbCoreMsgProducer();  
234 - transportNotificationsConsumer = queueProvider.createTransportNotificationsConsumer();  
235 - TopicPartitionInfo tpi = partitionService.getNotificationsTopic(ServiceType.TB_TRANSPORT, serviceInfoProvider.getServiceId());  
236 - transportNotificationsConsumer.subscribe(Collections.singleton(tpi));  
237 - transportApiRequestTemplate.init();  
238 - mainConsumerExecutor = Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("transport-consumer"));  
239 - }  
240 -  
241 - @AfterStartUp  
242 - private void start() {  
243 - mainConsumerExecutor.execute(() -> {  
244 - while (!stopped) {  
245 - try {  
246 - List<TbProtoQueueMsg<ToTransportMsg>> records = transportNotificationsConsumer.poll(notificationsPollDuration);  
247 - if (records.size() == 0) {  
248 - continue;  
249 - }  
250 - records.forEach(record -> {  
251 - try {  
252 - processToTransportMsg(record.getValue());  
253 - } catch (Throwable e) {  
254 - log.warn("Failed to process the notification.", e);  
255 - }  
256 - });  
257 - transportNotificationsConsumer.commit();  
258 - } catch (Exception e) {  
259 - if (!stopped) {  
260 - log.warn("Failed to obtain messages from queue.", e);  
261 - try {  
262 - Thread.sleep(notificationsPollDuration);  
263 - } catch (InterruptedException e2) {  
264 - log.trace("Failed to wait until the server has capacity to handle new requests", e2);  
265 - } 127 + public static final String OVERWRITE_ACTIVITY_TIME = "overwriteActivityTime";
  128 + public static final String SESSION_EXPIRED_MESSAGE =
  129 + "Session has expired due to last activity time!";
  130 + public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_OPEN =
  131 + getSessionEventMsg(TransportProtos.SessionEvent.OPEN);
  132 + public static final TransportProtos.SessionEventMsg SESSION_EVENT_MSG_CLOSED =
  133 + getSessionEventMsg(TransportProtos.SessionEvent.CLOSED);
  134 + public static final TransportProtos.SessionCloseNotificationProto
  135 + SESSION_CLOSE_NOTIFICATION_PROTO =
  136 + TransportProtos.SessionCloseNotificationProto.newBuilder()
  137 + .setMessage(SESSION_EXPIRED_MESSAGE)
  138 + .build();
  139 + public static final TransportProtos.SubscribeToAttributeUpdatesMsg
  140 + SUBSCRIBE_TO_ATTRIBUTE_UPDATES_ASYNC_MSG =
  141 + TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder()
  142 + .setSessionType(TransportProtos.SessionType.ASYNC)
  143 + .build();
  144 + public static final TransportProtos.SubscribeToRPCMsg SUBSCRIBE_TO_RPC_ASYNC_MSG =
  145 + TransportProtos.SubscribeToRPCMsg.newBuilder()
  146 + .setSessionType(TransportProtos.SessionType.ASYNC)
  147 + .build();
  148 +
  149 + private final AtomicInteger atomicTs = new AtomicInteger(0);
  150 +
  151 + @Value("${transport.log.enabled:true}")
  152 + private boolean logEnabled;
  153 +
  154 + @Value("${transport.log.max_length:1024}")
  155 + private int logMaxLength;
  156 +
  157 + @Value("${transport.sessions.inactivity_timeout}")
  158 + private long sessionInactivityTimeout;
  159 +
  160 + @Value("${transport.sessions.report_timeout}")
  161 + private long sessionReportTimeout;
  162 +
  163 + @Value("${transport.client_side_rpc.timeout:60000}")
  164 + private long clientSideRpcTimeout;
  165 +
  166 + @Value("${queue.transport.poll_interval}")
  167 + private int notificationsPollDuration;
  168 +
  169 + @Value("${transport.stats.enabled:false}")
  170 + private boolean statsEnabled;
  171 +
  172 + private final Map<String, Number> statsMap = new LinkedHashMap<>();
  173 +
  174 + private final Gson gson = new Gson();
  175 + private final TbTransportQueueFactory queueProvider;
  176 + private final TbQueueProducerProvider producerProvider;
  177 + private final PartitionService partitionService;
  178 + private final TbServiceInfoProvider serviceInfoProvider;
  179 + private final StatsFactory statsFactory;
  180 + private final TransportDeviceProfileCache deviceProfileCache;
  181 + private final TransportTenantProfileCache tenantProfileCache;
  182 + private final TbApiUsageClient apiUsageClient;
  183 + private final TransportRateLimitService rateLimitService;
  184 + private final DataDecodingEncodingService dataDecodingEncodingService;
  185 + private final SchedulerComponent scheduler;
  186 + private final ApplicationEventPublisher eventPublisher;
  187 + private final TransportResourceCache transportResourceCache;
  188 +
  189 + protected TbQueueRequestTemplate<
  190 + TbProtoQueueMsg<TransportApiRequestMsg>, TbProtoQueueMsg<TransportApiResponseMsg>>
  191 + transportApiRequestTemplate;
  192 + protected TbQueueProducer<TbProtoQueueMsg<ToRuleEngineMsg>> ruleEngineMsgProducer;
  193 + protected TbQueueProducer<TbProtoQueueMsg<ToCoreMsg>> tbCoreMsgProducer;
  194 + protected TbQueueConsumer<TbProtoQueueMsg<ToTransportMsg>> transportNotificationsConsumer;
  195 +
  196 + protected MessagesStats ruleEngineProducerStats;
  197 + protected MessagesStats tbCoreProducerStats;
  198 + protected MessagesStats transportApiStats;
  199 +
  200 + protected ExecutorService transportCallbackExecutor;
  201 + private ExecutorService mainConsumerExecutor;
  202 +
  203 + private final ConcurrentMap<UUID, SessionMetaData> sessions = new ConcurrentHashMap<>();
  204 + private final ConcurrentMap<UUID, SessionActivityData> sessionsActivity =
  205 + new ConcurrentHashMap<>();
  206 + private final Map<String, RpcRequestMetadata> toServerRpcPendingMap = new ConcurrentHashMap<>();
  207 +
  208 + @Getter
  209 + /** TCP协议的鉴权脚本 */
  210 + private final ConcurrentSkipListSet<UUID> authScripts = new ConcurrentSkipListSet<>();
  211 +
  212 + private volatile boolean stopped = false;
  213 +
  214 + public DefaultTransportService(
  215 + TbServiceInfoProvider serviceInfoProvider,
  216 + TbTransportQueueFactory queueProvider,
  217 + TbQueueProducerProvider producerProvider,
  218 + PartitionService partitionService,
  219 + StatsFactory statsFactory,
  220 + TransportDeviceProfileCache deviceProfileCache,
  221 + TransportTenantProfileCache tenantProfileCache,
  222 + TbApiUsageClient apiUsageClient,
  223 + TransportRateLimitService rateLimitService,
  224 + DataDecodingEncodingService dataDecodingEncodingService,
  225 + SchedulerComponent scheduler,
  226 + TransportResourceCache transportResourceCache,
  227 + ApplicationEventPublisher eventPublisher) {
  228 + this.serviceInfoProvider = serviceInfoProvider;
  229 + this.queueProvider = queueProvider;
  230 + this.producerProvider = producerProvider;
  231 + this.partitionService = partitionService;
  232 + this.statsFactory = statsFactory;
  233 + this.deviceProfileCache = deviceProfileCache;
  234 + this.tenantProfileCache = tenantProfileCache;
  235 + this.apiUsageClient = apiUsageClient;
  236 + this.rateLimitService = rateLimitService;
  237 + this.dataDecodingEncodingService = dataDecodingEncodingService;
  238 + this.scheduler = scheduler;
  239 + this.transportResourceCache = transportResourceCache;
  240 + this.eventPublisher = eventPublisher;
  241 + }
  242 +
  243 + @PostConstruct
  244 + public void init() {
  245 + this.ruleEngineProducerStats =
  246 + statsFactory.createMessagesStats(StatsType.RULE_ENGINE.getName() + ".producer");
  247 + this.tbCoreProducerStats =
  248 + statsFactory.createMessagesStats(StatsType.CORE.getName() + ".producer");
  249 + this.transportApiStats =
  250 + statsFactory.createMessagesStats(StatsType.TRANSPORT.getName() + ".producer");
  251 + this.transportCallbackExecutor = ThingsBoardExecutors.newWorkStealingPool(20, getClass());
  252 + this.scheduler.scheduleAtFixedRate(
  253 + this::checkInactivityAndReportActivity,
  254 + new Random().nextInt((int) sessionReportTimeout),
  255 + sessionReportTimeout,
  256 + TimeUnit.MILLISECONDS);
  257 + this.scheduler.scheduleAtFixedRate(
  258 + this::invalidateRateLimits,
  259 + new Random().nextInt((int) sessionReportTimeout),
  260 + sessionReportTimeout,
  261 + TimeUnit.MILLISECONDS);
  262 + transportApiRequestTemplate = queueProvider.createTransportApiRequestTemplate();
  263 + transportApiRequestTemplate.setMessagesStats(transportApiStats);
  264 + ruleEngineMsgProducer = producerProvider.getRuleEngineMsgProducer();
  265 + tbCoreMsgProducer = producerProvider.getTbCoreMsgProducer();
  266 + transportNotificationsConsumer = queueProvider.createTransportNotificationsConsumer();
  267 + TopicPartitionInfo tpi =
  268 + partitionService.getNotificationsTopic(
  269 + ServiceType.TB_TRANSPORT, serviceInfoProvider.getServiceId());
  270 + transportNotificationsConsumer.subscribe(Collections.singleton(tpi));
  271 + transportApiRequestTemplate.init();
  272 + mainConsumerExecutor =
  273 + Executors.newSingleThreadExecutor(ThingsBoardThreadFactory.forName("transport-consumer"));
  274 + }
  275 +
  276 + @AfterStartUp
  277 + private void start() {
  278 + mainConsumerExecutor.execute(
  279 + () -> {
  280 + while (!stopped) {
  281 + try {
  282 + List<TbProtoQueueMsg<ToTransportMsg>> records =
  283 + transportNotificationsConsumer.poll(notificationsPollDuration);
  284 + if (records.size() == 0) {
  285 + continue;
  286 + }
  287 + records.forEach(
  288 + record -> {
  289 + try {
  290 + processToTransportMsg(record.getValue());
  291 + } catch (Throwable e) {
  292 + log.warn("Failed to process the notification.", e);
266 } 293 }
  294 + });
  295 + transportNotificationsConsumer.commit();
  296 + } catch (Exception e) {
  297 + if (!stopped) {
  298 + log.warn("Failed to obtain messages from queue.", e);
  299 + try {
  300 + Thread.sleep(notificationsPollDuration);
  301 + } catch (InterruptedException e2) {
  302 + log.trace(
  303 + "Failed to wait until the server has capacity to handle new requests", e2);
267 } 304 }
  305 + }
268 } 306 }
  307 + }
269 }); 308 });
270 - }  
271 -  
272 - private void invalidateRateLimits() {  
273 - rateLimitService.invalidateRateLimitsIpTable(sessionInactivityTimeout);  
274 - }  
275 -  
276 - @PreDestroy  
277 - public void destroy() {  
278 - stopped = true;  
279 -  
280 - if (transportNotificationsConsumer != null) {  
281 - transportNotificationsConsumer.unsubscribe();  
282 - }  
283 - if (transportCallbackExecutor != null) {  
284 - transportCallbackExecutor.shutdownNow();  
285 - }  
286 - if (mainConsumerExecutor != null) {  
287 - mainConsumerExecutor.shutdownNow();  
288 - }  
289 - if (transportApiRequestTemplate != null) {  
290 - transportApiRequestTemplate.stop();  
291 - }  
292 - }  
293 -  
294 - @Override  
295 - public SessionMetaData registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) {  
296 - return sessions.computeIfAbsent(toSessionId(sessionInfo), (x) -> new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener));  
297 - }  
298 -  
299 - @Override  
300 - public TransportProtos.GetEntityProfileResponseMsg getEntityProfile(TransportProtos.GetEntityProfileRequestMsg msg) {  
301 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =  
302 - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setEntityProfileRequestMsg(msg).build());  
303 - try {  
304 - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get();  
305 - return response.getValue().getEntityProfileResponseMsg();  
306 - } catch (InterruptedException | ExecutionException e) {  
307 - throw new RuntimeException(e);  
308 - }  
309 - }  
310 -  
311 - @Override  
312 - public TransportProtos.GetResourceResponseMsg getResource(TransportProtos.GetResourceRequestMsg msg) {  
313 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =  
314 - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setResourceRequestMsg(msg).build());  
315 - try {  
316 - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get();  
317 - return response.getValue().getResourceResponseMsg();  
318 - } catch (InterruptedException | ExecutionException e) {  
319 - throw new RuntimeException(e);  
320 - }  
321 - }  
322 -  
323 -  
324 -  
325 - @Override  
326 - public TransportProtos.GetSnmpDevicesResponseMsg getSnmpDevicesIds(TransportProtos.GetSnmpDevicesRequestMsg requestMsg) {  
327 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(  
328 - UUID.randomUUID(), TransportApiRequestMsg.newBuilder()  
329 - .setSnmpDevicesRequestMsg(requestMsg)  
330 - .build()  
331 - );  
332 -  
333 - try {  
334 - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get();  
335 - return response.getValue().getSnmpDevicesResponseMsg();  
336 - } catch (InterruptedException | ExecutionException e) {  
337 - throw new RuntimeException(e);  
338 - }  
339 - }  
340 -  
341 - @Override  
342 - public TransportProtos.GetDeviceResponseMsg getDevice(TransportProtos.GetDeviceRequestMsg requestMsg) {  
343 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(  
344 - UUID.randomUUID(), TransportApiRequestMsg.newBuilder()  
345 - .setDeviceRequestMsg(requestMsg)  
346 - .build()  
347 - );  
348 -  
349 - try {  
350 - TransportApiResponseMsg response = transportApiRequestTemplate.send(protoMsg).get().getValue();  
351 - if (response.hasDeviceResponseMsg()) {  
352 - return response.getDeviceResponseMsg();  
353 - } else {  
354 - return null;  
355 - }  
356 - } catch (InterruptedException | ExecutionException e) {  
357 - throw new RuntimeException(e);  
358 - }  
359 - }  
360 -  
361 - @Override  
362 - public TransportProtos.GetDeviceCredentialsResponseMsg getDeviceCredentials(TransportProtos.GetDeviceCredentialsRequestMsg requestMsg) {  
363 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(  
364 - UUID.randomUUID(), TransportApiRequestMsg.newBuilder()  
365 - .setDeviceCredentialsRequestMsg(requestMsg)  
366 - .build()  
367 - );  
368 -  
369 - try {  
370 - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get();  
371 - return response.getValue().getDeviceCredentialsResponseMsg();  
372 - } catch (InterruptedException | ExecutionException e) {  
373 - throw new RuntimeException(e);  
374 - }  
375 - }  
376 -  
377 - @Override  
378 - public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceTokenRequestMsg msg,  
379 - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {  
380 - log.trace("Processing msg: {}", msg);  
381 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(),  
382 - TransportApiRequestMsg.newBuilder().setValidateTokenRequestMsg(msg).build());  
383 - doProcess(transportType, protoMsg, callback);  
384 - }  
385 -  
386 - @Override  
387 - public void process(DeviceTransportType transportType, TransportProtos.ValidateBasicMqttCredRequestMsg msg,  
388 - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {  
389 - log.trace("Processing msg: {}", msg);  
390 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(),  
391 - TransportApiRequestMsg.newBuilder().setValidateBasicMqttCredRequestMsg(msg).build());  
392 - doProcess(transportType, protoMsg, callback);  
393 - }  
394 -  
395 - @Override  
396 - public void process(TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg requestMsg, TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {  
397 - log.trace("Processing msg: {}", requestMsg);  
398 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateDeviceLwM2MCredentialsRequestMsg(requestMsg).build());  
399 - ListenableFuture<ValidateDeviceCredentialsResponse> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> {  
400 - TransportProtos.ValidateDeviceCredentialsResponseMsg msg = tmp.getValue().getValidateCredResponseMsg();  
401 - ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result = ValidateDeviceCredentialsResponse.builder();  
402 - if (msg.hasDeviceInfo()) { 309 + }
  310 +
  311 + private void invalidateRateLimits() {
  312 + rateLimitService.invalidateRateLimitsIpTable(sessionInactivityTimeout);
  313 + }
  314 +
  315 + @PreDestroy
  316 + public void destroy() {
  317 + stopped = true;
  318 +
  319 + if (transportNotificationsConsumer != null) {
  320 + transportNotificationsConsumer.unsubscribe();
  321 + }
  322 + if (transportCallbackExecutor != null) {
  323 + transportCallbackExecutor.shutdownNow();
  324 + }
  325 + if (mainConsumerExecutor != null) {
  326 + mainConsumerExecutor.shutdownNow();
  327 + }
  328 + if (transportApiRequestTemplate != null) {
  329 + transportApiRequestTemplate.stop();
  330 + }
  331 + }
  332 +
  333 + @Override
  334 + public SessionMetaData registerAsyncSession(
  335 + TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) {
  336 + return sessions.computeIfAbsent(
  337 + toSessionId(sessionInfo),
  338 + (x) -> new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener));
  339 + }
  340 +
  341 + @Override
  342 + public TransportProtos.GetEntityProfileResponseMsg getEntityProfile(
  343 + TransportProtos.GetEntityProfileRequestMsg msg) {
  344 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  345 + new TbProtoQueueMsg<>(
  346 + UUID.randomUUID(),
  347 + TransportApiRequestMsg.newBuilder().setEntityProfileRequestMsg(msg).build());
  348 + try {
  349 + TbProtoQueueMsg<TransportApiResponseMsg> response =
  350 + transportApiRequestTemplate.send(protoMsg).get();
  351 + return response.getValue().getEntityProfileResponseMsg();
  352 + } catch (InterruptedException | ExecutionException e) {
  353 + throw new RuntimeException(e);
  354 + }
  355 + }
  356 +
  357 + @Override
  358 + public TransportProtos.GetResourceResponseMsg getResource(
  359 + TransportProtos.GetResourceRequestMsg msg) {
  360 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  361 + new TbProtoQueueMsg<>(
  362 + UUID.randomUUID(),
  363 + TransportApiRequestMsg.newBuilder().setResourceRequestMsg(msg).build());
  364 + try {
  365 + TbProtoQueueMsg<TransportApiResponseMsg> response =
  366 + transportApiRequestTemplate.send(protoMsg).get();
  367 + return response.getValue().getResourceResponseMsg();
  368 + } catch (InterruptedException | ExecutionException e) {
  369 + throw new RuntimeException(e);
  370 + }
  371 + }
  372 +
  373 + @Override
  374 + public TransportProtos.GetSnmpDevicesResponseMsg getSnmpDevicesIds(
  375 + TransportProtos.GetSnmpDevicesRequestMsg requestMsg) {
  376 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  377 + new TbProtoQueueMsg<>(
  378 + UUID.randomUUID(),
  379 + TransportApiRequestMsg.newBuilder().setSnmpDevicesRequestMsg(requestMsg).build());
  380 +
  381 + try {
  382 + TbProtoQueueMsg<TransportApiResponseMsg> response =
  383 + transportApiRequestTemplate.send(protoMsg).get();
  384 + return response.getValue().getSnmpDevicesResponseMsg();
  385 + } catch (InterruptedException | ExecutionException e) {
  386 + throw new RuntimeException(e);
  387 + }
  388 + }
  389 +
  390 + @Override
  391 + public TransportProtos.GetDeviceResponseMsg getDevice(
  392 + TransportProtos.GetDeviceRequestMsg requestMsg) {
  393 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  394 + new TbProtoQueueMsg<>(
  395 + UUID.randomUUID(),
  396 + TransportApiRequestMsg.newBuilder().setDeviceRequestMsg(requestMsg).build());
  397 +
  398 + try {
  399 + TransportApiResponseMsg response =
  400 + transportApiRequestTemplate.send(protoMsg).get().getValue();
  401 + if (response.hasDeviceResponseMsg()) {
  402 + return response.getDeviceResponseMsg();
  403 + } else {
  404 + return null;
  405 + }
  406 + } catch (InterruptedException | ExecutionException e) {
  407 + throw new RuntimeException(e);
  408 + }
  409 + }
  410 +
  411 + @Override
  412 + public TransportProtos.GetDeviceCredentialsResponseMsg getDeviceCredentials(
  413 + TransportProtos.GetDeviceCredentialsRequestMsg requestMsg) {
  414 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  415 + new TbProtoQueueMsg<>(
  416 + UUID.randomUUID(),
  417 + TransportApiRequestMsg.newBuilder().setDeviceCredentialsRequestMsg(requestMsg).build());
  418 +
  419 + try {
  420 + TbProtoQueueMsg<TransportApiResponseMsg> response =
  421 + transportApiRequestTemplate.send(protoMsg).get();
  422 + return response.getValue().getDeviceCredentialsResponseMsg();
  423 + } catch (InterruptedException | ExecutionException e) {
  424 + throw new RuntimeException(e);
  425 + }
  426 + }
  427 +
  428 + @Override
  429 + public void process(
  430 + DeviceTransportType transportType,
  431 + TransportProtos.ValidateDeviceTokenRequestMsg msg,
  432 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
  433 + log.trace("Processing msg: {}", msg);
  434 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  435 + new TbProtoQueueMsg<>(
  436 + UUID.randomUUID(),
  437 + TransportApiRequestMsg.newBuilder().setValidateTokenRequestMsg(msg).build());
  438 + doProcess(transportType, protoMsg, callback);
  439 + }
  440 +
  441 + @Override
  442 + public void process(
  443 + DeviceTransportType transportType,
  444 + TransportProtos.ValidateBasicMqttCredRequestMsg msg,
  445 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
  446 + log.trace("Processing msg: {}", msg);
  447 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  448 + new TbProtoQueueMsg<>(
  449 + UUID.randomUUID(),
  450 + TransportApiRequestMsg.newBuilder().setValidateBasicMqttCredRequestMsg(msg).build());
  451 + doProcess(transportType, protoMsg, callback);
  452 + }
  453 +
  454 + @Override
  455 + public void process(
  456 + TransportProtos.ValidateDeviceLwM2MCredentialsRequestMsg requestMsg,
  457 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
  458 + log.trace("Processing msg: {}", requestMsg);
  459 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  460 + new TbProtoQueueMsg<>(
  461 + UUID.randomUUID(),
  462 + TransportApiRequestMsg.newBuilder()
  463 + .setValidateDeviceLwM2MCredentialsRequestMsg(requestMsg)
  464 + .build());
  465 + ListenableFuture<ValidateDeviceCredentialsResponse> response =
  466 + Futures.transform(
  467 + transportApiRequestTemplate.send(protoMsg),
  468 + tmp -> {
  469 + TransportProtos.ValidateDeviceCredentialsResponseMsg msg =
  470 + tmp.getValue().getValidateCredResponseMsg();
  471 + ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result =
  472 + ValidateDeviceCredentialsResponse.builder();
  473 + if (msg.hasDeviceInfo()) {
403 result.credentials(msg.getCredentialsBody()); 474 result.credentials(msg.getCredentialsBody());
404 TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); 475 TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo());
405 result.deviceInfo(tdi); 476 result.deviceInfo(tdi);
406 ByteString profileBody = msg.getProfileBody(); 477 ByteString profileBody = msg.getProfileBody();
407 if (!profileBody.isEmpty()) { 478 if (!profileBody.isEmpty()) {
408 - DeviceProfile profile = deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody);  
409 - result.deviceProfile(profile); 479 + DeviceProfile profile =
  480 + deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody);
  481 + result.deviceProfile(profile);
410 } 482 }
411 - }  
412 - return result.build();  
413 - }, MoreExecutors.directExecutor());  
414 - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor);  
415 - }  
416 -  
417 - @Override  
418 - public void process(DeviceTransportType transportType, TransportProtos.ValidateDeviceX509CertRequestMsg msg, TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {  
419 - log.trace("Processing msg: {}", msg);  
420 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setValidateX509CertRequestMsg(msg).build());  
421 - doProcess(transportType, protoMsg, callback);  
422 - }  
423 -  
424 - private void doProcess(DeviceTransportType transportType, TbProtoQueueMsg<TransportApiRequestMsg> protoMsg,  
425 - TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {  
426 - ListenableFuture<ValidateDeviceCredentialsResponse> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> {  
427 - TransportProtos.ValidateDeviceCredentialsResponseMsg msg = tmp.getValue().getValidateCredResponseMsg();  
428 - ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result = ValidateDeviceCredentialsResponse.builder();  
429 - if (msg.hasDeviceInfo()) { 483 + }
  484 + return result.build();
  485 + },
  486 + MoreExecutors.directExecutor());
  487 + AsyncCallbackTemplate.withCallback(
  488 + response, callback::onSuccess, callback::onError, transportCallbackExecutor);
  489 + }
  490 +
  491 + @Override
  492 + public void process(
  493 + DeviceTransportType transportType,
  494 + TransportProtos.ValidateDeviceX509CertRequestMsg msg,
  495 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
  496 + log.trace("Processing msg: {}", msg);
  497 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  498 + new TbProtoQueueMsg<>(
  499 + UUID.randomUUID(),
  500 + TransportApiRequestMsg.newBuilder().setValidateX509CertRequestMsg(msg).build());
  501 + doProcess(transportType, protoMsg, callback);
  502 + }
  503 +
  504 + private void doProcess(
  505 + DeviceTransportType transportType,
  506 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg,
  507 + TransportServiceCallback<ValidateDeviceCredentialsResponse> callback) {
  508 +
  509 + ListenableFuture<ValidateDeviceCredentialsResponse> response =
  510 + Futures.transform(
  511 + transportApiRequestTemplate.send(protoMsg),
  512 + tmp -> {
  513 + TransportProtos.ValidateDeviceCredentialsResponseMsg msg =
  514 + tmp.getValue().getValidateCredResponseMsg();
  515 + ValidateDeviceCredentialsResponse.ValidateDeviceCredentialsResponseBuilder result =
  516 + ValidateDeviceCredentialsResponse.builder();
  517 + if (msg.hasDeviceInfo()) {
430 result.credentials(msg.getCredentialsBody()); 518 result.credentials(msg.getCredentialsBody());
431 TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); 519 TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo());
432 result.deviceInfo(tdi); 520 result.deviceInfo(tdi);
433 ByteString profileBody = msg.getProfileBody(); 521 ByteString profileBody = msg.getProfileBody();
434 if (!profileBody.isEmpty()) { 522 if (!profileBody.isEmpty()) {
435 - DeviceProfile profile = deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody);  
436 - if (transportType != DeviceTransportType.DEFAULT  
437 - && profile != null && profile.getTransportType() != DeviceTransportType.DEFAULT && profile.getTransportType() != transportType) {  
438 - log.debug("[{}] Device profile [{}] has different transport type: {}, expected: {}", tdi.getDeviceId(), tdi.getDeviceProfileId(), profile.getTransportType(), transportType);  
439 - throw new IllegalStateException("Device profile has different transport type: " + profile.getTransportType() + ". Expected: " + transportType);  
440 - }  
441 - result.deviceProfile(profile); 523 + DeviceProfile profile =
  524 + deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody);
  525 + if (transportType != DeviceTransportType.DEFAULT
  526 + && profile != null
  527 + && profile.getTransportType() != DeviceTransportType.DEFAULT
  528 + && profile.getTransportType() != transportType) {
  529 + log.debug(
  530 + "[{}] Device profile [{}] has different transport type: {}, expected: {}",
  531 + tdi.getDeviceId(),
  532 + tdi.getDeviceProfileId(),
  533 + profile.getTransportType(),
  534 + transportType);
  535 + throw new IllegalStateException(
  536 + "Device profile has different transport type: "
  537 + + profile.getTransportType()
  538 + + ". Expected: "
  539 + + transportType);
  540 + }
  541 + result.deviceProfile(profile);
442 } 542 }
443 - }  
444 - return result.build();  
445 - }, MoreExecutors.directExecutor());  
446 - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor);  
447 - }  
448 -  
449 - @Override  
450 - public void process(TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg requestMsg, TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback) {  
451 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setGetOrCreateDeviceRequestMsg(requestMsg).build());  
452 - log.trace("Processing msg: {}", requestMsg);  
453 - ListenableFuture<GetOrCreateDeviceFromGatewayResponse> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp -> {  
454 - TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg msg = tmp.getValue().getGetOrCreateDeviceResponseMsg();  
455 - GetOrCreateDeviceFromGatewayResponse.GetOrCreateDeviceFromGatewayResponseBuilder result = GetOrCreateDeviceFromGatewayResponse.builder();  
456 - if (msg.hasDeviceInfo()) { 543 + }
  544 + return result.build();
  545 + },
  546 + MoreExecutors.directExecutor());
  547 + AsyncCallbackTemplate.withCallback(
  548 + response, callback::onSuccess, callback::onError, transportCallbackExecutor);
  549 + }
  550 +
  551 + @Override
  552 + public void process(
  553 + TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg requestMsg,
  554 + TransportServiceCallback<GetOrCreateDeviceFromGatewayResponse> callback) {
  555 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  556 + new TbProtoQueueMsg<>(
  557 + UUID.randomUUID(),
  558 + TransportApiRequestMsg.newBuilder().setGetOrCreateDeviceRequestMsg(requestMsg).build());
  559 + log.trace("Processing msg: {}", requestMsg);
  560 + ListenableFuture<GetOrCreateDeviceFromGatewayResponse> response =
  561 + Futures.transform(
  562 + transportApiRequestTemplate.send(protoMsg),
  563 + tmp -> {
  564 + TransportProtos.GetOrCreateDeviceFromGatewayResponseMsg msg =
  565 + tmp.getValue().getGetOrCreateDeviceResponseMsg();
  566 + GetOrCreateDeviceFromGatewayResponse.GetOrCreateDeviceFromGatewayResponseBuilder
  567 + result = GetOrCreateDeviceFromGatewayResponse.builder();
  568 + if (msg.hasDeviceInfo()) {
457 TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo()); 569 TransportDeviceInfo tdi = getTransportDeviceInfo(msg.getDeviceInfo());
458 result.deviceInfo(tdi); 570 result.deviceInfo(tdi);
459 ByteString profileBody = msg.getProfileBody(); 571 ByteString profileBody = msg.getProfileBody();
460 if (profileBody != null && !profileBody.isEmpty()) { 572 if (profileBody != null && !profileBody.isEmpty()) {
461 - result.deviceProfile(deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody)); 573 + result.deviceProfile(
  574 + deviceProfileCache.getOrCreate(tdi.getDeviceProfileId(), profileBody));
462 } 575 }
463 - }  
464 - return result.build();  
465 - }, MoreExecutors.directExecutor());  
466 - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor);  
467 - }  
468 -  
469 - @Override  
470 - public void process(TransportProtos.LwM2MRequestMsg msg, TransportServiceCallback<TransportProtos.LwM2MResponseMsg> callback) {  
471 - log.trace("Processing msg: {}", msg);  
472 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(),  
473 - TransportApiRequestMsg.newBuilder().setLwM2MRequestMsg(msg).build());  
474 - AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg),  
475 - response -> callback.onSuccess(response.getValue().getLwM2MResponseMsg()), callback::onError, transportCallbackExecutor);  
476 - }  
477 -  
478 - private TransportDeviceInfo getTransportDeviceInfo(TransportProtos.DeviceInfoProto di) {  
479 - TransportDeviceInfo tdi = new TransportDeviceInfo();  
480 - tdi.setTenantId(TenantId.fromUUID(new UUID(di.getTenantIdMSB(), di.getTenantIdLSB())));  
481 - tdi.setCustomerId(new CustomerId(new UUID(di.getCustomerIdMSB(), di.getCustomerIdLSB())));  
482 - tdi.setDeviceId(new DeviceId(new UUID(di.getDeviceIdMSB(), di.getDeviceIdLSB())));  
483 - tdi.setDeviceProfileId(new DeviceProfileId(new UUID(di.getDeviceProfileIdMSB(), di.getDeviceProfileIdLSB())));  
484 - tdi.setAdditionalInfo(di.getAdditionalInfo());  
485 - tdi.setDeviceName(di.getDeviceName());  
486 - tdi.setDeviceType(di.getDeviceType());  
487 - if (StringUtils.isNotEmpty(di.getPowerMode())) {  
488 - tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode()));  
489 - tdi.setEdrxCycle(di.getEdrxCycle());  
490 - tdi.setPsmActivityTimer(di.getPsmActivityTimer());  
491 - tdi.setPagingTransmissionWindow(di.getPagingTransmissionWindow());  
492 - }  
493 - return tdi;  
494 - }  
495 -  
496 - @Override  
497 - public void process(ProvisionDeviceRequestMsg requestMsg, TransportServiceCallback<ProvisionDeviceResponseMsg> callback) {  
498 - log.trace("Processing msg: {}", requestMsg);  
499 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg = new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setProvisionDeviceRequestMsg(requestMsg).build());  
500 - ListenableFuture<ProvisionDeviceResponseMsg> response = Futures.transform(transportApiRequestTemplate.send(protoMsg), tmp ->  
501 - tmp.getValue().getProvisionDeviceResponseMsg()  
502 - , MoreExecutors.directExecutor());  
503 - AsyncCallbackTemplate.withCallback(response, callback::onSuccess, callback::onError, transportCallbackExecutor);  
504 - }  
505 -  
506 - @Override  
507 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SubscriptionInfoProto msg, TransportServiceCallback<Void> callback) {  
508 - if (log.isTraceEnabled()) {  
509 - log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg); 576 + }
  577 + return result.build();
  578 + },
  579 + MoreExecutors.directExecutor());
  580 + AsyncCallbackTemplate.withCallback(
  581 + response, callback::onSuccess, callback::onError, transportCallbackExecutor);
  582 + }
  583 +
  584 + @Override
  585 + public void process(
  586 + TransportProtos.LwM2MRequestMsg msg,
  587 + TransportServiceCallback<TransportProtos.LwM2MResponseMsg> callback) {
  588 + log.trace("Processing msg: {}", msg);
  589 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  590 + new TbProtoQueueMsg<>(
  591 + UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setLwM2MRequestMsg(msg).build());
  592 + AsyncCallbackTemplate.withCallback(
  593 + transportApiRequestTemplate.send(protoMsg),
  594 + response -> callback.onSuccess(response.getValue().getLwM2MResponseMsg()),
  595 + callback::onError,
  596 + transportCallbackExecutor);
  597 + }
  598 +
  599 + private TransportDeviceInfo getTransportDeviceInfo(TransportProtos.DeviceInfoProto di) {
  600 + TransportDeviceInfo tdi = new TransportDeviceInfo();
  601 + tdi.setTenantId(TenantId.fromUUID(new UUID(di.getTenantIdMSB(), di.getTenantIdLSB())));
  602 + tdi.setCustomerId(new CustomerId(new UUID(di.getCustomerIdMSB(), di.getCustomerIdLSB())));
  603 + tdi.setDeviceId(new DeviceId(new UUID(di.getDeviceIdMSB(), di.getDeviceIdLSB())));
  604 + tdi.setDeviceProfileId(
  605 + new DeviceProfileId(new UUID(di.getDeviceProfileIdMSB(), di.getDeviceProfileIdLSB())));
  606 + tdi.setAdditionalInfo(di.getAdditionalInfo());
  607 + tdi.setDeviceName(di.getDeviceName());
  608 + tdi.setDeviceType(di.getDeviceType());
  609 + if (StringUtils.isNotEmpty(di.getPowerMode())) {
  610 + tdi.setPowerMode(PowerMode.valueOf(di.getPowerMode()));
  611 + tdi.setEdrxCycle(di.getEdrxCycle());
  612 + tdi.setPsmActivityTimer(di.getPsmActivityTimer());
  613 + tdi.setPagingTransmissionWindow(di.getPagingTransmissionWindow());
  614 + }
  615 + return tdi;
  616 + }
  617 +
  618 + @Override
  619 + public void process(
  620 + ProvisionDeviceRequestMsg requestMsg,
  621 + TransportServiceCallback<ProvisionDeviceResponseMsg> callback) {
  622 + log.trace("Processing msg: {}", requestMsg);
  623 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  624 + new TbProtoQueueMsg<>(
  625 + UUID.randomUUID(),
  626 + TransportApiRequestMsg.newBuilder().setProvisionDeviceRequestMsg(requestMsg).build());
  627 + ListenableFuture<ProvisionDeviceResponseMsg> response =
  628 + Futures.transform(
  629 + transportApiRequestTemplate.send(protoMsg),
  630 + tmp -> tmp.getValue().getProvisionDeviceResponseMsg(),
  631 + MoreExecutors.directExecutor());
  632 + AsyncCallbackTemplate.withCallback(
  633 + response, callback::onSuccess, callback::onError, transportCallbackExecutor);
  634 + }
  635 +
  636 + @Override
  637 + public void process(
  638 + TransportProtos.SessionInfoProto sessionInfo,
  639 + TransportProtos.SubscriptionInfoProto msg,
  640 + TransportServiceCallback<Void> callback) {
  641 + if (log.isTraceEnabled()) {
  642 + log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg);
  643 + }
  644 + sendToDeviceActor(
  645 + sessionInfo,
  646 + TransportToDeviceActorMsg.newBuilder()
  647 + .setSessionInfo(sessionInfo)
  648 + .setSubscriptionInfo(msg)
  649 + .build(),
  650 + callback);
  651 + }
  652 +
  653 + @Override
  654 + public void process(
  655 + TransportProtos.SessionInfoProto sessionInfo,
  656 + TransportProtos.SessionEventMsg msg,
  657 + TransportServiceCallback<Void> callback) {
  658 + if (checkLimits(sessionInfo, msg, callback)) {
  659 + reportActivityInternal(sessionInfo);
  660 + sendToDeviceActor(
  661 + sessionInfo,
  662 + TransportToDeviceActorMsg.newBuilder()
  663 + .setSessionInfo(sessionInfo)
  664 + .setSessionEvent(msg)
  665 + .build(),
  666 + callback);
  667 + }
  668 + }
  669 +
  670 + @Override
  671 + public void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback) {
  672 + TransportProtos.SessionInfoProto sessionInfo = msg.getSessionInfo();
  673 + if (checkLimits(sessionInfo, msg, callback)) {
  674 + SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo));
  675 + if (sessionMetaData != null) {
  676 + if (msg.hasSubscribeToAttributes()) {
  677 + sessionMetaData.setSubscribedToAttributes(true);
510 } 678 }
511 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)  
512 - .setSubscriptionInfo(msg).build(), callback);  
513 - }  
514 -  
515 - @Override  
516 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SessionEventMsg msg, TransportServiceCallback<Void> callback) {  
517 - if (checkLimits(sessionInfo, msg, callback)) {  
518 - reportActivityInternal(sessionInfo);  
519 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)  
520 - .setSessionEvent(msg).build(), callback); 679 + if (msg.hasSubscribeToRPC()) {
  680 + sessionMetaData.setSubscribedToRPC(true);
521 } 681 }
522 - }  
523 -  
524 - @Override  
525 - public void process(TransportToDeviceActorMsg msg, TransportServiceCallback<Void> callback) {  
526 - TransportProtos.SessionInfoProto sessionInfo = msg.getSessionInfo();  
527 - if (checkLimits(sessionInfo, msg, callback)) {  
528 - SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo));  
529 - if (sessionMetaData != null) {  
530 - if (msg.hasSubscribeToAttributes()) {  
531 - sessionMetaData.setSubscribedToAttributes(true);  
532 - }  
533 - if (msg.hasSubscribeToRPC()) {  
534 - sessionMetaData.setSubscribedToRPC(true);  
535 - }  
536 - }  
537 -  
538 - reportActivityInternal(sessionInfo);  
539 - sendToDeviceActor(sessionInfo, msg, callback);  
540 - }  
541 - }  
542 -  
543 - @Override  
544 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.PostTelemetryMsg msg, TransportServiceCallback<Void> callback) {  
545 - int dataPoints = 0;  
546 - for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) {  
547 - dataPoints += tsKv.getKvCount();  
548 - }  
549 - if (checkLimits(sessionInfo, msg, callback, dataPoints)) {  
550 - reportActivityInternal(sessionInfo);  
551 - TenantId tenantId = getTenantId(sessionInfo);  
552 - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));  
553 - CustomerId customerId = getCustomerId(sessionInfo);  
554 - MsgPackCallback packCallback = new MsgPackCallback(msg.getTsKvListCount(), new ApiStatsProxyCallback<>(tenantId, customerId, dataPoints, callback));  
555 - for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) {  
556 - TbMsgMetaData metaData = new TbMsgMetaData();  
557 - metaData.putValue("deviceName", sessionInfo.getDeviceName());  
558 - metaData.putValue("deviceType", sessionInfo.getDeviceType());  
559 - metaData.putValue("ts", tsKv.getTs() + "");  
560 - JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList());  
561 - sendToRuleEngine(tenantId, deviceId, customerId, sessionInfo, json, metaData, SessionMsgType.POST_TELEMETRY_REQUEST, packCallback);  
562 - }  
563 - }  
564 - }  
565 -  
566 - @Override  
567 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.PostAttributeMsg msg, TransportServiceCallback<Void> callback) {  
568 - if (checkLimits(sessionInfo, msg, callback, msg.getKvCount())) {  
569 - reportActivityInternal(sessionInfo);  
570 - TenantId tenantId = getTenantId(sessionInfo);  
571 - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));  
572 - JsonObject json = JsonUtils.getJsonObject(msg.getKvList());  
573 - TbMsgMetaData metaData = new TbMsgMetaData();  
574 - metaData.putValue("deviceName", sessionInfo.getDeviceName());  
575 - metaData.putValue("deviceType", sessionInfo.getDeviceType());  
576 - metaData.putValue("notifyDevice", "false");  
577 - CustomerId customerId = getCustomerId(sessionInfo);  
578 - sendToRuleEngine(tenantId, deviceId, customerId, sessionInfo, json, metaData, SessionMsgType.POST_ATTRIBUTES_REQUEST,  
579 - new TransportTbQueueCallback(new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback)));  
580 - }  
581 - }  
582 - //thingskit  
583 - @Override  
584 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.PostEventMsg msg,  
585 - TransportServiceCallback<Void> callback,String topicName) {  
586 - //Topic地址:v1/devices/event/${deviceIdentifier}/${identifier}  
587 - //${deviceIdentifier} 标识支持deviceId/deviceName即SN  
588 - String[] topicInfo = topicName.split(MqttTopics.BASE_DEVICE_EVENT_TOPIC + "/");  
589 - if(null == topicInfo || topicInfo.length !=2){  
590 - throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage());  
591 - }  
592 - String[] eventInfo = topicInfo[1].split("/");  
593 - if(null == eventInfo || eventInfo.length !=2){  
594 - throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage());  
595 - }  
596 - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB())); 682 + }
  683 +
  684 + reportActivityInternal(sessionInfo);
  685 + sendToDeviceActor(sessionInfo, msg, callback);
  686 + }
  687 + }
  688 +
  689 + @Override
  690 + public void process(
  691 + TransportProtos.SessionInfoProto sessionInfo,
  692 + TransportProtos.PostTelemetryMsg msg,
  693 + TransportServiceCallback<Void> callback) {
  694 + int dataPoints = 0;
  695 + for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) {
  696 + dataPoints += tsKv.getKvCount();
  697 + }
  698 + if (checkLimits(sessionInfo, msg, callback, dataPoints)) {
  699 + reportActivityInternal(sessionInfo);
  700 + TenantId tenantId = getTenantId(sessionInfo);
  701 + DeviceId deviceId =
  702 + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
  703 + CustomerId customerId = getCustomerId(sessionInfo);
  704 + MsgPackCallback packCallback =
  705 + new MsgPackCallback(
  706 + msg.getTsKvListCount(),
  707 + new ApiStatsProxyCallback<>(tenantId, customerId, dataPoints, callback));
  708 + for (TransportProtos.TsKvListProto tsKv : msg.getTsKvListList()) {
597 TbMsgMetaData metaData = new TbMsgMetaData(); 709 TbMsgMetaData metaData = new TbMsgMetaData();
598 - String selfData = FastIotConstants.YES;  
599 - String eventDeviceId = eventInfo[0];  
600 - //通过设备名称或设备ID上报自己的事件  
601 - if(sessionInfo.getDeviceName().equals(eventInfo[0]) || eventDeviceId.equals(deviceId.toString())){  
602 - eventDeviceId = deviceId.toString();  
603 - }else{  
604 - //网关上报网关子设备的事件  
605 - selfData = FastIotConstants.NO;  
606 - }  
607 - reportActivityInternal(sessionInfo);  
608 - JsonObject json = JsonUtils.getJsonObject(msg.getKvList());  
609 - json.addProperty(EVENT_IDENTIFIER,eventInfo[1]);  
610 - CustomerId customerId = getCustomerId(sessionInfo);  
611 - TenantId tenantId = getTenantId(sessionInfo);  
612 metaData.putValue("deviceName", sessionInfo.getDeviceName()); 710 metaData.putValue("deviceName", sessionInfo.getDeviceName());
613 metaData.putValue("deviceType", sessionInfo.getDeviceType()); 711 metaData.putValue("deviceType", sessionInfo.getDeviceType());
614 - metaData.putValue("deviceId",eventDeviceId);  
615 - metaData.putValue(EVENT_IDENTIFIER, eventInfo[1]);  
616 - metaData.putValue("selfData",selfData);  
617 - sendToRuleEngine(tenantId, deviceId, customerId, sessionInfo, json, metaData, SessionMsgType.POST_EVENT_REQUEST,  
618 - new TransportTbQueueCallback(new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback)));  
619 - }  
620 -  
621 - @Override  
622 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.GetAttributeRequestMsg msg, TransportServiceCallback<Void> callback) {  
623 - if (checkLimits(sessionInfo, msg, callback)) {  
624 - reportActivityInternal(sessionInfo);  
625 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)  
626 - .setGetAttributes(msg).build(), new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback)); 712 + metaData.putValue("ts", tsKv.getTs() + "");
  713 + JsonObject json = JsonUtils.getJsonObject(tsKv.getKvList());
  714 + sendToRuleEngine(
  715 + tenantId,
  716 + deviceId,
  717 + customerId,
  718 + sessionInfo,
  719 + json,
  720 + metaData,
  721 + SessionMsgType.POST_TELEMETRY_REQUEST,
  722 + packCallback);
  723 + }
  724 + }
  725 + }
  726 +
  727 + @Override
  728 + public void process(
  729 + TransportProtos.SessionInfoProto sessionInfo,
  730 + TransportProtos.PostAttributeMsg msg,
  731 + TransportServiceCallback<Void> callback) {
  732 + if (checkLimits(sessionInfo, msg, callback, msg.getKvCount())) {
  733 + reportActivityInternal(sessionInfo);
  734 + TenantId tenantId = getTenantId(sessionInfo);
  735 + DeviceId deviceId =
  736 + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
  737 + JsonObject json = JsonUtils.getJsonObject(msg.getKvList());
  738 + TbMsgMetaData metaData = new TbMsgMetaData();
  739 + metaData.putValue("deviceName", sessionInfo.getDeviceName());
  740 + metaData.putValue("deviceType", sessionInfo.getDeviceType());
  741 + metaData.putValue("notifyDevice", "false");
  742 + CustomerId customerId = getCustomerId(sessionInfo);
  743 + sendToRuleEngine(
  744 + tenantId,
  745 + deviceId,
  746 + customerId,
  747 + sessionInfo,
  748 + json,
  749 + metaData,
  750 + SessionMsgType.POST_ATTRIBUTES_REQUEST,
  751 + new TransportTbQueueCallback(
  752 + new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback)));
  753 + }
  754 + }
  755 +
  756 + // thingskit
  757 + @Override
  758 + public void process(
  759 + TransportProtos.SessionInfoProto sessionInfo,
  760 + TransportProtos.PostEventMsg msg,
  761 + TransportServiceCallback<Void> callback,
  762 + String topicName) {
  763 + // Topic地址:v1/devices/event/${deviceIdentifier}/${identifier}
  764 + // ${deviceIdentifier} 标识支持deviceId/deviceName即SN
  765 + String[] topicInfo = topicName.split(MqttTopics.BASE_DEVICE_EVENT_TOPIC + "/");
  766 + if (null == topicInfo || topicInfo.length != 2) {
  767 + throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage());
  768 + }
  769 + String[] eventInfo = topicInfo[1].split("/");
  770 + if (null == eventInfo || eventInfo.length != 2) {
  771 + throw new TkDataValidationException(ErrorMessage.INVALID_TOPIC.getMessage());
  772 + }
  773 + DeviceId deviceId =
  774 + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
  775 + TbMsgMetaData metaData = new TbMsgMetaData();
  776 + String selfData = FastIotConstants.YES;
  777 + String eventDeviceId = eventInfo[0];
  778 + // 通过设备名称或设备ID上报自己的事件
  779 + if (sessionInfo.getDeviceName().equals(eventInfo[0])
  780 + || eventDeviceId.equals(deviceId.toString())) {
  781 + eventDeviceId = deviceId.toString();
  782 + } else {
  783 + // 网关上报网关子设备的事件
  784 + selfData = FastIotConstants.NO;
  785 + }
  786 + reportActivityInternal(sessionInfo);
  787 + JsonObject json = JsonUtils.getJsonObject(msg.getKvList());
  788 + json.addProperty(EVENT_IDENTIFIER, eventInfo[1]);
  789 + CustomerId customerId = getCustomerId(sessionInfo);
  790 + TenantId tenantId = getTenantId(sessionInfo);
  791 + metaData.putValue("deviceName", sessionInfo.getDeviceName());
  792 + metaData.putValue("deviceType", sessionInfo.getDeviceType());
  793 + metaData.putValue("deviceId", eventDeviceId);
  794 + metaData.putValue(EVENT_IDENTIFIER, eventInfo[1]);
  795 + metaData.putValue("selfData", selfData);
  796 + sendToRuleEngine(
  797 + tenantId,
  798 + deviceId,
  799 + customerId,
  800 + sessionInfo,
  801 + json,
  802 + metaData,
  803 + SessionMsgType.POST_EVENT_REQUEST,
  804 + new TransportTbQueueCallback(
  805 + new ApiStatsProxyCallback<>(tenantId, customerId, msg.getKvList().size(), callback)));
  806 + }
  807 +
  808 + @Override
  809 + public void process(
  810 + TransportProtos.SessionInfoProto sessionInfo,
  811 + TransportProtos.GetAttributeRequestMsg msg,
  812 + TransportServiceCallback<Void> callback) {
  813 + if (checkLimits(sessionInfo, msg, callback)) {
  814 + reportActivityInternal(sessionInfo);
  815 + sendToDeviceActor(
  816 + sessionInfo,
  817 + TransportToDeviceActorMsg.newBuilder()
  818 + .setSessionInfo(sessionInfo)
  819 + .setGetAttributes(msg)
  820 + .build(),
  821 + new ApiStatsProxyCallback<>(
  822 + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));
  823 + }
  824 + }
  825 +
  826 + @Override
  827 + public void process(
  828 + TransportProtos.SessionInfoProto sessionInfo,
  829 + TransportProtos.SubscribeToAttributeUpdatesMsg msg,
  830 + TransportServiceCallback<Void> callback) {
  831 + if (checkLimits(sessionInfo, msg, callback)) {
  832 + SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo));
  833 + if (sessionMetaData != null) {
  834 + sessionMetaData.setSubscribedToAttributes(!msg.getUnsubscribe());
  835 + }
  836 + reportActivityInternal(sessionInfo);
  837 + sendToDeviceActor(
  838 + sessionInfo,
  839 + TransportToDeviceActorMsg.newBuilder()
  840 + .setSessionInfo(sessionInfo)
  841 + .setSubscribeToAttributes(msg)
  842 + .build(),
  843 + new ApiStatsProxyCallback<>(
  844 + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));
  845 + }
  846 + }
  847 +
  848 + @Override
  849 + public void process(
  850 + TransportProtos.SessionInfoProto sessionInfo,
  851 + TransportProtos.SubscribeToRPCMsg msg,
  852 + TransportServiceCallback<Void> callback) {
  853 + if (checkLimits(sessionInfo, msg, callback)) {
  854 + SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo));
  855 + if (sessionMetaData != null) {
  856 + sessionMetaData.setSubscribedToRPC(!msg.getUnsubscribe());
  857 + }
  858 + reportActivityInternal(sessionInfo);
  859 + sendToDeviceActor(
  860 + sessionInfo,
  861 + TransportToDeviceActorMsg.newBuilder()
  862 + .setSessionInfo(sessionInfo)
  863 + .setSubscribeToRPC(msg)
  864 + .build(),
  865 + new ApiStatsProxyCallback<>(
  866 + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));
  867 + }
  868 + }
  869 +
  870 + @Override
  871 + public void process(
  872 + TransportProtos.SessionInfoProto sessionInfo,
  873 + TransportProtos.ToDeviceRpcResponseMsg msg,
  874 + TransportServiceCallback<Void> callback) {
  875 + if (checkLimits(sessionInfo, msg, callback)) {
  876 + reportActivityInternal(sessionInfo);
  877 + sendToDeviceActor(
  878 + sessionInfo,
  879 + TransportToDeviceActorMsg.newBuilder()
  880 + .setSessionInfo(sessionInfo)
  881 + .setToDeviceRPCCallResponse(msg)
  882 + .build(),
  883 + new ApiStatsProxyCallback<>(
  884 + getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));
  885 + }
  886 + }
  887 +
  888 + @Override
  889 + public void notifyAboutUplink(
  890 + TransportProtos.SessionInfoProto sessionInfo,
  891 + TransportProtos.UplinkNotificationMsg msg,
  892 + TransportServiceCallback<Void> callback) {
  893 + if (checkLimits(sessionInfo, msg, callback)) {
  894 + reportActivityInternal(sessionInfo);
  895 + sendToDeviceActor(
  896 + sessionInfo,
  897 + TransportToDeviceActorMsg.newBuilder()
  898 + .setSessionInfo(sessionInfo)
  899 + .setUplinkNotificationMsg(msg)
  900 + .build(),
  901 + callback);
  902 + }
  903 + }
  904 +
  905 + @Override
  906 + public void process(
  907 + TransportProtos.SessionInfoProto sessionInfo,
  908 + TransportProtos.ToDeviceRpcRequestMsg msg,
  909 + RpcStatus rpcStatus,
  910 + TransportServiceCallback<Void> callback) {
  911 + TransportProtos.ToDeviceRpcResponseStatusMsg responseMsg =
  912 + TransportProtos.ToDeviceRpcResponseStatusMsg.newBuilder()
  913 + .setRequestId(msg.getRequestId())
  914 + .setRequestIdLSB(msg.getRequestIdLSB())
  915 + .setRequestIdMSB(msg.getRequestIdMSB())
  916 + .setStatus(rpcStatus.name())
  917 + .build();
  918 +
  919 + if (checkLimits(sessionInfo, responseMsg, callback)) {
  920 + reportActivityInternal(sessionInfo);
  921 + sendToDeviceActor(
  922 + sessionInfo,
  923 + TransportToDeviceActorMsg.newBuilder()
  924 + .setSessionInfo(sessionInfo)
  925 + .setRpcResponseStatusMsg(responseMsg)
  926 + .build(),
  927 + new ApiStatsProxyCallback<>(
  928 + getTenantId(sessionInfo),
  929 + getCustomerId(sessionInfo),
  930 + 1,
  931 + TransportServiceCallback.EMPTY));
  932 + }
  933 + }
  934 +
  935 + private void processTimeout(String requestId) {
  936 + RpcRequestMetadata data = toServerRpcPendingMap.remove(requestId);
  937 + if (data != null) {
  938 + SessionMetaData md = sessions.get(data.getSessionId());
  939 + if (md != null) {
  940 + SessionMsgListener listener = md.getListener();
  941 + transportCallbackExecutor.submit(
  942 + () -> {
  943 + TransportProtos.ToServerRpcResponseMsg responseMsg =
  944 + TransportProtos.ToServerRpcResponseMsg.newBuilder()
  945 + .setRequestId(data.getRequestId())
  946 + .setError("timeout")
  947 + .build();
  948 + listener.onToServerRpcResponse(responseMsg);
  949 + });
  950 + if (md.getSessionType() == TransportProtos.SessionType.SYNC) {
  951 + deregisterSession(md.getSessionInfo());
627 } 952 }
628 - }  
629 -  
630 - @Override  
631 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg msg, TransportServiceCallback<Void> callback) {  
632 - if (checkLimits(sessionInfo, msg, callback)) {  
633 - SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo));  
634 - if (sessionMetaData != null) {  
635 - sessionMetaData.setSubscribedToAttributes(!msg.getUnsubscribe()); 953 + } else {
  954 + log.debug("[{}] Missing session.", data.getSessionId());
  955 + }
  956 + }
  957 + }
  958 +
  959 + @Override
  960 + public void process(
  961 + TransportProtos.SessionInfoProto sessionInfo,
  962 + TransportProtos.ToServerRpcRequestMsg msg,
  963 + TransportServiceCallback<Void> callback) {
  964 + if (checkLimits(sessionInfo, msg, callback)) {
  965 + reportActivityInternal(sessionInfo);
  966 + UUID sessionId = toSessionId(sessionInfo);
  967 + TenantId tenantId = getTenantId(sessionInfo);
  968 + DeviceId deviceId = getDeviceId(sessionInfo);
  969 + JsonObject json = new JsonObject();
  970 + json.addProperty("method", msg.getMethodName());
  971 + json.add("params", JsonUtils.parse(msg.getParams()));
  972 +
  973 + TbMsgMetaData metaData = new TbMsgMetaData();
  974 + metaData.putValue("deviceName", sessionInfo.getDeviceName());
  975 + metaData.putValue("deviceType", sessionInfo.getDeviceType());
  976 + metaData.putValue("requestId", Integer.toString(msg.getRequestId()));
  977 + metaData.putValue("serviceId", serviceInfoProvider.getServiceId());
  978 + metaData.putValue("sessionId", sessionId.toString());
  979 + sendToRuleEngine(
  980 + tenantId,
  981 + deviceId,
  982 + getCustomerId(sessionInfo),
  983 + sessionInfo,
  984 + json,
  985 + metaData,
  986 + SessionMsgType.TO_SERVER_RPC_REQUEST,
  987 + new TransportTbQueueCallback(callback));
  988 + String requestId = sessionId + "-" + msg.getRequestId();
  989 + toServerRpcPendingMap.put(requestId, new RpcRequestMetadata(sessionId, msg.getRequestId()));
  990 + scheduler.schedule(
  991 + () -> processTimeout(requestId), clientSideRpcTimeout, TimeUnit.MILLISECONDS);
  992 + }
  993 + }
  994 +
  995 + @Override
  996 + public void process(
  997 + TransportProtos.SessionInfoProto sessionInfo,
  998 + TransportProtos.ClaimDeviceMsg msg,
  999 + TransportServiceCallback<Void> callback) {
  1000 + if (checkLimits(sessionInfo, msg, callback)) {
  1001 + reportActivityInternal(sessionInfo);
  1002 + sendToDeviceActor(
  1003 + sessionInfo,
  1004 + TransportToDeviceActorMsg.newBuilder()
  1005 + .setSessionInfo(sessionInfo)
  1006 + .setClaimDevice(msg)
  1007 + .build(),
  1008 + callback);
  1009 + }
  1010 + }
  1011 +
  1012 + @Override
  1013 + public void process(
  1014 + TransportProtos.SessionInfoProto sessionInfo,
  1015 + TransportProtos.GetOtaPackageRequestMsg msg,
  1016 + TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> callback) {
  1017 + if (checkLimits(sessionInfo, msg, callback)) {
  1018 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  1019 + new TbProtoQueueMsg<>(
  1020 + UUID.randomUUID(),
  1021 + TransportApiRequestMsg.newBuilder().setOtaPackageRequestMsg(msg).build());
  1022 +
  1023 + AsyncCallbackTemplate.withCallback(
  1024 + transportApiRequestTemplate.send(protoMsg),
  1025 + response -> {
  1026 + callback.onSuccess(response.getValue().getOtaPackageResponseMsg());
  1027 + },
  1028 + callback::onError,
  1029 + transportCallbackExecutor);
  1030 + }
  1031 + }
  1032 +
  1033 + @Override
  1034 + public void reportActivity(TransportProtos.SessionInfoProto sessionInfo) {
  1035 + reportActivityInternal(sessionInfo);
  1036 + }
  1037 +
  1038 + private void reportActivityInternal(TransportProtos.SessionInfoProto sessionInfo) {
  1039 + UUID sessionId = toSessionId(sessionInfo);
  1040 + SessionActivityData sessionMetaData =
  1041 + sessionsActivity.computeIfAbsent(sessionId, id -> new SessionActivityData(sessionInfo));
  1042 + sessionMetaData.updateLastActivityTime();
  1043 + }
  1044 +
  1045 + private void checkInactivityAndReportActivity() {
  1046 + long expTime = System.currentTimeMillis() - sessionInactivityTimeout;
  1047 + Set<UUID> sessionsToRemove = new HashSet<>();
  1048 + sessionsActivity.forEach(
  1049 + (uuid, sessionAD) -> {
  1050 + long lastActivityTime = sessionAD.getLastActivityTime();
  1051 + SessionMetaData sessionMD = sessions.get(uuid);
  1052 + if (sessionMD != null) {
  1053 + sessionAD.setSessionInfo(sessionMD.getSessionInfo());
  1054 + } else {
  1055 + sessionsToRemove.add(uuid);
  1056 + }
  1057 + TransportProtos.SessionInfoProto sessionInfo = sessionAD.getSessionInfo();
  1058 +
  1059 + if (sessionInfo.getGwSessionIdMSB() != 0 && sessionInfo.getGwSessionIdLSB() != 0) {
  1060 + var gwSessionId =
  1061 + new UUID(sessionInfo.getGwSessionIdMSB(), sessionInfo.getGwSessionIdLSB());
  1062 + SessionMetaData gwMetaData = sessions.get(gwSessionId);
  1063 + SessionActivityData gwActivityData = sessionsActivity.get(gwSessionId);
  1064 + if (gwMetaData != null && gwMetaData.isOverwriteActivityTime()) {
  1065 + lastActivityTime = Math.max(gwActivityData.getLastActivityTime(), lastActivityTime);
636 } 1066 }
637 - reportActivityInternal(sessionInfo);  
638 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSubscribeToAttributes(msg).build(),  
639 - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));  
640 - }  
641 - }  
642 -  
643 - @Override  
644 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.SubscribeToRPCMsg msg, TransportServiceCallback<Void> callback) {  
645 - if (checkLimits(sessionInfo, msg, callback)) {  
646 - SessionMetaData sessionMetaData = sessions.get(toSessionId(sessionInfo));  
647 - if (sessionMetaData != null) {  
648 - sessionMetaData.setSubscribedToRPC(!msg.getUnsubscribe()); 1067 + }
  1068 + if (lastActivityTime < expTime) {
  1069 + if (sessionMD != null) {
  1070 + if (log.isDebugEnabled()) {
  1071 + log.debug(
  1072 + "[{}] Session has expired due to last activity time: {}",
  1073 + toSessionId(sessionInfo),
  1074 + lastActivityTime);
  1075 + }
  1076 + sessions.remove(uuid);
  1077 + sessionsToRemove.add(uuid);
  1078 + process(sessionInfo, SESSION_EVENT_MSG_CLOSED, null);
  1079 + sessionMD
  1080 + .getListener()
  1081 + .onRemoteSessionCloseCommand(uuid, SESSION_CLOSE_NOTIFICATION_PROTO);
649 } 1082 }
650 - reportActivityInternal(sessionInfo);  
651 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setSubscribeToRPC(msg).build(),  
652 - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));  
653 - }  
654 - }  
655 -  
656 - @Override  
657 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcResponseMsg msg, TransportServiceCallback<Void> callback) {  
658 - if (checkLimits(sessionInfo, msg, callback)) {  
659 - reportActivityInternal(sessionInfo);  
660 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setToDeviceRPCCallResponse(msg).build(),  
661 - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, callback));  
662 - }  
663 - }  
664 -  
665 - @Override  
666 - public void notifyAboutUplink(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.UplinkNotificationMsg msg, TransportServiceCallback<Void> callback) {  
667 - if (checkLimits(sessionInfo, msg, callback)) {  
668 - reportActivityInternal(sessionInfo);  
669 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setUplinkNotificationMsg(msg).build(), callback);  
670 - }  
671 - }  
672 -  
673 - @Override  
674 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToDeviceRpcRequestMsg msg, RpcStatus rpcStatus, TransportServiceCallback<Void> callback) {  
675 - TransportProtos.ToDeviceRpcResponseStatusMsg responseMsg = TransportProtos.ToDeviceRpcResponseStatusMsg.newBuilder()  
676 - .setRequestId(msg.getRequestId())  
677 - .setRequestIdLSB(msg.getRequestIdLSB())  
678 - .setRequestIdMSB(msg.getRequestIdMSB())  
679 - .setStatus(rpcStatus.name())  
680 - .build();  
681 -  
682 - if (checkLimits(sessionInfo, responseMsg, callback)) {  
683 - reportActivityInternal(sessionInfo);  
684 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo).setRpcResponseStatusMsg(responseMsg).build(),  
685 - new ApiStatsProxyCallback<>(getTenantId(sessionInfo), getCustomerId(sessionInfo), 1, TransportServiceCallback.EMPTY));  
686 - }  
687 - } 1083 + } else {
  1084 + if (lastActivityTime > sessionAD.getLastReportedActivityTime()) {
  1085 + final long lastActivityTimeFinal = lastActivityTime;
  1086 + process(
  1087 + sessionInfo,
  1088 + TransportProtos.SubscriptionInfoProto.newBuilder()
  1089 + .setAttributeSubscription(
  1090 + sessionMD != null && sessionMD.isSubscribedToAttributes())
  1091 + .setRpcSubscription(sessionMD != null && sessionMD.isSubscribedToRPC())
  1092 + .setLastActivityTime(lastActivityTime)
  1093 + .build(),
  1094 + new TransportServiceCallback<Void>() {
  1095 + @Override
  1096 + public void onSuccess(Void msg) {
  1097 + sessionAD.setLastReportedActivityTime(lastActivityTimeFinal);
  1098 + }
688 1099
689 - private void processTimeout(String requestId) {  
690 - RpcRequestMetadata data = toServerRpcPendingMap.remove(requestId);  
691 - if (data != null) {  
692 - SessionMetaData md = sessions.get(data.getSessionId());  
693 - if (md != null) {  
694 - SessionMsgListener listener = md.getListener();  
695 - transportCallbackExecutor.submit(() -> {  
696 - TransportProtos.ToServerRpcResponseMsg responseMsg =  
697 - TransportProtos.ToServerRpcResponseMsg.newBuilder()  
698 - .setRequestId(data.getRequestId())  
699 - .setError("timeout").build();  
700 - listener.onToServerRpcResponse(responseMsg);  
701 - });  
702 - if (md.getSessionType() == TransportProtos.SessionType.SYNC) {  
703 - deregisterSession(md.getSessionInfo());  
704 - }  
705 - } else {  
706 - log.debug("[{}] Missing session.", data.getSessionId()); 1100 + @Override
  1101 + public void onError(Throwable e) {
  1102 + log.warn("[{}] Failed to report last activity time", uuid, e);
  1103 + }
  1104 + });
707 } 1105 }
708 - }  
709 - }  
710 -  
711 - @Override  
712 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ToServerRpcRequestMsg msg, TransportServiceCallback<Void> callback) {  
713 - if (checkLimits(sessionInfo, msg, callback)) {  
714 - reportActivityInternal(sessionInfo);  
715 - UUID sessionId = toSessionId(sessionInfo);  
716 - TenantId tenantId = getTenantId(sessionInfo);  
717 - DeviceId deviceId = getDeviceId(sessionInfo);  
718 - JsonObject json = new JsonObject();  
719 - json.addProperty("method", msg.getMethodName());  
720 - json.add("params", JsonUtils.parse(msg.getParams()));  
721 -  
722 - TbMsgMetaData metaData = new TbMsgMetaData();  
723 - metaData.putValue("deviceName", sessionInfo.getDeviceName());  
724 - metaData.putValue("deviceType", sessionInfo.getDeviceType());  
725 - metaData.putValue("requestId", Integer.toString(msg.getRequestId()));  
726 - metaData.putValue("serviceId", serviceInfoProvider.getServiceId());  
727 - metaData.putValue("sessionId", sessionId.toString());  
728 - sendToRuleEngine(tenantId, deviceId, getCustomerId(sessionInfo), sessionInfo, json, metaData,  
729 - SessionMsgType.TO_SERVER_RPC_REQUEST, new TransportTbQueueCallback(callback));  
730 - String requestId = sessionId + "-" + msg.getRequestId();  
731 - toServerRpcPendingMap.put(requestId, new RpcRequestMetadata(sessionId, msg.getRequestId()));  
732 - scheduler.schedule(() -> processTimeout(requestId), clientSideRpcTimeout, TimeUnit.MILLISECONDS);  
733 - }  
734 - }  
735 -  
736 - @Override  
737 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.ClaimDeviceMsg msg, TransportServiceCallback<Void> callback) {  
738 - if (checkLimits(sessionInfo, msg, callback)) {  
739 - reportActivityInternal(sessionInfo);  
740 - sendToDeviceActor(sessionInfo, TransportToDeviceActorMsg.newBuilder().setSessionInfo(sessionInfo)  
741 - .setClaimDevice(msg).build(), callback);  
742 - }  
743 - }  
744 -  
745 - @Override  
746 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.GetOtaPackageRequestMsg msg, TransportServiceCallback<TransportProtos.GetOtaPackageResponseMsg> callback) {  
747 - if (checkLimits(sessionInfo, msg, callback)) {  
748 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =  
749 - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setOtaPackageRequestMsg(msg).build());  
750 -  
751 - AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), response -> {  
752 - callback.onSuccess(response.getValue().getOtaPackageResponseMsg());  
753 - }, callback::onError, transportCallbackExecutor);  
754 - }  
755 - }  
756 -  
757 - @Override  
758 - public void reportActivity(TransportProtos.SessionInfoProto sessionInfo) {  
759 - reportActivityInternal(sessionInfo);  
760 - }  
761 -  
762 - private void reportActivityInternal(TransportProtos.SessionInfoProto sessionInfo) {  
763 - UUID sessionId = toSessionId(sessionInfo);  
764 - SessionActivityData sessionMetaData = sessionsActivity.computeIfAbsent(sessionId, id -> new SessionActivityData(sessionInfo));  
765 - sessionMetaData.updateLastActivityTime();  
766 - }  
767 -  
768 - private void checkInactivityAndReportActivity() {  
769 - long expTime = System.currentTimeMillis() - sessionInactivityTimeout;  
770 - Set<UUID> sessionsToRemove = new HashSet<>();  
771 - sessionsActivity.forEach((uuid, sessionAD) -> {  
772 - long lastActivityTime = sessionAD.getLastActivityTime();  
773 - SessionMetaData sessionMD = sessions.get(uuid);  
774 - if (sessionMD != null) {  
775 - sessionAD.setSessionInfo(sessionMD.getSessionInfo());  
776 - } else {  
777 - sessionsToRemove.add(uuid); 1106 + }
  1107 + });
  1108 + // Removes all closed or short-lived sessions.
  1109 + sessionsToRemove.forEach(sessionsActivity::remove);
  1110 + }
  1111 +
  1112 + @Override
  1113 + public SessionMetaData registerSyncSession(
  1114 + TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout) {
  1115 + SessionMetaData currentSession =
  1116 + new SessionMetaData(sessionInfo, TransportProtos.SessionType.SYNC, listener);
  1117 + UUID sessionId = toSessionId(sessionInfo);
  1118 + sessions.putIfAbsent(sessionId, currentSession);
  1119 +
  1120 + TransportProtos.SessionCloseNotificationProto notification =
  1121 + TransportProtos.SessionCloseNotificationProto.newBuilder()
  1122 + .setMessage("session timeout!")
  1123 + .build();
  1124 +
  1125 + ScheduledFuture executorFuture =
  1126 + scheduler.schedule(
  1127 + () -> {
  1128 + listener.onRemoteSessionCloseCommand(sessionId, notification);
  1129 + deregisterSession(sessionInfo);
  1130 + },
  1131 + timeout,
  1132 + TimeUnit.MILLISECONDS);
  1133 +
  1134 + currentSession.setScheduledFuture(executorFuture);
  1135 + return currentSession;
  1136 + }
  1137 +
  1138 + @Override
  1139 + public void deregisterSession(TransportProtos.SessionInfoProto sessionInfo) {
  1140 + SessionMetaData currentSession = sessions.get(toSessionId(sessionInfo));
  1141 + if (currentSession != null && currentSession.hasScheduledFuture()) {
  1142 + log.debug("Stopping scheduler to avoid resending response if request has been ack.");
  1143 + currentSession.getScheduledFuture().cancel(false);
  1144 + }
  1145 + sessions.remove(toSessionId(sessionInfo));
  1146 + }
  1147 +
  1148 + @Override
  1149 + public void log(TransportProtos.SessionInfoProto sessionInfo, String msg) {
  1150 + if (!logEnabled || sessionInfo == null || StringUtils.isEmpty(msg)) {
  1151 + return;
  1152 + }
  1153 + if (msg.length() > logMaxLength) {
  1154 + msg = msg.substring(0, logMaxLength);
  1155 + }
  1156 + TransportProtos.PostTelemetryMsg.Builder request =
  1157 + TransportProtos.PostTelemetryMsg.newBuilder();
  1158 + TransportProtos.TsKvListProto.Builder builder = TransportProtos.TsKvListProto.newBuilder();
  1159 + builder.setTs(
  1160 + TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L
  1161 + + (atomicTs.getAndIncrement() % 1000));
  1162 + builder.addKv(
  1163 + TransportProtos.KeyValueProto.newBuilder()
  1164 + .setKey("transportLog")
  1165 + .setType(TransportProtos.KeyValueType.STRING_V)
  1166 + .setStringV(msg)
  1167 + .build());
  1168 + request.addTsKvList(builder.build());
  1169 + TransportProtos.PostTelemetryMsg postTelemetryMsg = request.build();
  1170 + process(sessionInfo, postTelemetryMsg, TransportServiceCallback.EMPTY);
  1171 + }
  1172 +
  1173 + private boolean checkLimits(
  1174 + TransportProtos.SessionInfoProto sessionInfo,
  1175 + Object msg,
  1176 + TransportServiceCallback<?> callback) {
  1177 + return checkLimits(sessionInfo, msg, callback, 0);
  1178 + }
  1179 +
  1180 + private boolean checkLimits(
  1181 + TransportProtos.SessionInfoProto sessionInfo,
  1182 + Object msg,
  1183 + TransportServiceCallback<?> callback,
  1184 + int dataPoints) {
  1185 + if (log.isTraceEnabled()) {
  1186 + log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg);
  1187 + }
  1188 + TenantId tenantId =
  1189 + TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB()));
  1190 + DeviceId deviceId =
  1191 + new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
  1192 +
  1193 + EntityType rateLimitedEntityType = rateLimitService.checkLimits(tenantId, deviceId, dataPoints);
  1194 + if (rateLimitedEntityType == null) {
  1195 + return true;
  1196 + } else {
  1197 + if (callback != null) {
  1198 + callback.onError(new TbRateLimitsException(rateLimitedEntityType));
  1199 + }
  1200 + return false;
  1201 + }
  1202 + }
  1203 +
  1204 + protected void processToTransportMsg(ToTransportMsg toSessionMsg) {
  1205 + UUID sessionId = new UUID(toSessionMsg.getSessionIdMSB(), toSessionMsg.getSessionIdLSB());
  1206 + SessionMetaData md = sessions.get(sessionId);
  1207 + if (md != null) {
  1208 + log.trace("[{}] Processing notification: {}", sessionId, toSessionMsg);
  1209 + SessionMsgListener listener = md.getListener();
  1210 + transportCallbackExecutor.submit(
  1211 + () -> {
  1212 + if (toSessionMsg.hasGetAttributesResponse()) {
  1213 + listener.onGetAttributesResponse(toSessionMsg.getGetAttributesResponse());
778 } 1214 }
779 - TransportProtos.SessionInfoProto sessionInfo = sessionAD.getSessionInfo();  
780 -  
781 - if (sessionInfo.getGwSessionIdMSB() != 0 && sessionInfo.getGwSessionIdLSB() != 0) {  
782 - var gwSessionId = new UUID(sessionInfo.getGwSessionIdMSB(), sessionInfo.getGwSessionIdLSB());  
783 - SessionMetaData gwMetaData = sessions.get(gwSessionId);  
784 - SessionActivityData gwActivityData = sessionsActivity.get(gwSessionId);  
785 - if (gwMetaData != null && gwMetaData.isOverwriteActivityTime()) {  
786 - lastActivityTime = Math.max(gwActivityData.getLastActivityTime(), lastActivityTime);  
787 - } 1215 + if (toSessionMsg.hasAttributeUpdateNotification()) {
  1216 + listener.onAttributeUpdate(sessionId, toSessionMsg.getAttributeUpdateNotification());
788 } 1217 }
789 - if (lastActivityTime < expTime) {  
790 - if (sessionMD != null) {  
791 - if (log.isDebugEnabled()) {  
792 - log.debug("[{}] Session has expired due to last activity time: {}", toSessionId(sessionInfo), lastActivityTime);  
793 - }  
794 - sessions.remove(uuid);  
795 - sessionsToRemove.add(uuid);  
796 - process(sessionInfo, SESSION_EVENT_MSG_CLOSED, null);  
797 - sessionMD.getListener().onRemoteSessionCloseCommand(uuid, SESSION_CLOSE_NOTIFICATION_PROTO);  
798 - }  
799 - } else {  
800 - if (lastActivityTime > sessionAD.getLastReportedActivityTime()) {  
801 - final long lastActivityTimeFinal = lastActivityTime;  
802 - process(sessionInfo, TransportProtos.SubscriptionInfoProto.newBuilder()  
803 - .setAttributeSubscription(sessionMD != null && sessionMD.isSubscribedToAttributes())  
804 - .setRpcSubscription(sessionMD != null && sessionMD.isSubscribedToRPC())  
805 - .setLastActivityTime(lastActivityTime).build(), new TransportServiceCallback<Void>() {  
806 - @Override  
807 - public void onSuccess(Void msg) {  
808 - sessionAD.setLastReportedActivityTime(lastActivityTimeFinal);  
809 - }  
810 -  
811 - @Override  
812 - public void onError(Throwable e) {  
813 - log.warn("[{}] Failed to report last activity time", uuid, e);  
814 - }  
815 - });  
816 - } 1218 + if (toSessionMsg.hasSessionCloseNotification()) {
  1219 + listener.onRemoteSessionCloseCommand(
  1220 + sessionId, toSessionMsg.getSessionCloseNotification());
817 } 1221 }
818 - });  
819 - // Removes all closed or short-lived sessions.  
820 - sessionsToRemove.forEach(sessionsActivity::remove);  
821 - }  
822 -  
823 - @Override  
824 - public SessionMetaData registerSyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout) {  
825 - SessionMetaData currentSession = new SessionMetaData(sessionInfo, TransportProtos.SessionType.SYNC, listener);  
826 - UUID sessionId = toSessionId(sessionInfo);  
827 - sessions.putIfAbsent(sessionId, currentSession);  
828 -  
829 - TransportProtos.SessionCloseNotificationProto notification = TransportProtos.SessionCloseNotificationProto.newBuilder().setMessage("session timeout!").build();  
830 -  
831 - ScheduledFuture executorFuture = scheduler.schedule(() -> {  
832 - listener.onRemoteSessionCloseCommand(sessionId, notification);  
833 - deregisterSession(sessionInfo);  
834 - }, timeout, TimeUnit.MILLISECONDS);  
835 -  
836 - currentSession.setScheduledFuture(executorFuture);  
837 - return currentSession;  
838 - }  
839 -  
840 - @Override  
841 - public void deregisterSession(TransportProtos.SessionInfoProto sessionInfo) {  
842 - SessionMetaData currentSession = sessions.get(toSessionId(sessionInfo));  
843 - if (currentSession != null && currentSession.hasScheduledFuture()) {  
844 - log.debug("Stopping scheduler to avoid resending response if request has been ack.");  
845 - currentSession.getScheduledFuture().cancel(false);  
846 - }  
847 - sessions.remove(toSessionId(sessionInfo));  
848 - }  
849 -  
850 - @Override  
851 - public void log(TransportProtos.SessionInfoProto sessionInfo, String msg) {  
852 - if (!logEnabled || sessionInfo == null || StringUtils.isEmpty(msg)) {  
853 - return;  
854 - }  
855 - if (msg.length() > logMaxLength) {  
856 - msg = msg.substring(0, logMaxLength);  
857 - }  
858 - TransportProtos.PostTelemetryMsg.Builder request = TransportProtos.PostTelemetryMsg.newBuilder();  
859 - TransportProtos.TsKvListProto.Builder builder = TransportProtos.TsKvListProto.newBuilder();  
860 - builder.setTs(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) * 1000L + (atomicTs.getAndIncrement() % 1000));  
861 - builder.addKv(TransportProtos.KeyValueProto.newBuilder()  
862 - .setKey("transportLog")  
863 - .setType(TransportProtos.KeyValueType.STRING_V)  
864 - .setStringV(msg).build());  
865 - request.addTsKvList(builder.build());  
866 - TransportProtos.PostTelemetryMsg postTelemetryMsg = request.build();  
867 - process(sessionInfo, postTelemetryMsg, TransportServiceCallback.EMPTY);  
868 - }  
869 -  
870 - private boolean checkLimits(TransportProtos.SessionInfoProto sessionInfo, Object msg, TransportServiceCallback<?> callback) {  
871 - return checkLimits(sessionInfo, msg, callback, 0);  
872 - }  
873 -  
874 - private boolean checkLimits(TransportProtos.SessionInfoProto sessionInfo, Object msg, TransportServiceCallback<?> callback, int dataPoints) {  
875 - if (log.isTraceEnabled()) {  
876 - log.trace("[{}] Processing msg: {}", toSessionId(sessionInfo), msg);  
877 - }  
878 - TenantId tenantId = TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB()));  
879 - DeviceId deviceId = new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));  
880 -  
881 - EntityType rateLimitedEntityType = rateLimitService.checkLimits(tenantId, deviceId, dataPoints);  
882 - if (rateLimitedEntityType == null) {  
883 - return true;  
884 - } else {  
885 - if (callback != null) {  
886 - callback.onError(new TbRateLimitsException(rateLimitedEntityType)); 1222 + if (toSessionMsg.hasToTransportUpdateCredentialsNotification()) {
  1223 + listener.onToTransportUpdateCredentials(
  1224 + toSessionMsg.getToTransportUpdateCredentialsNotification());
887 } 1225 }
888 - return false;  
889 - }  
890 - }  
891 -  
892 - protected void processToTransportMsg(ToTransportMsg toSessionMsg) {  
893 - UUID sessionId = new UUID(toSessionMsg.getSessionIdMSB(), toSessionMsg.getSessionIdLSB());  
894 - SessionMetaData md = sessions.get(sessionId);  
895 - if (md != null) {  
896 - log.trace("[{}] Processing notification: {}", sessionId, toSessionMsg);  
897 - SessionMsgListener listener = md.getListener();  
898 - transportCallbackExecutor.submit(() -> {  
899 - if (toSessionMsg.hasGetAttributesResponse()) {  
900 - listener.onGetAttributesResponse(toSessionMsg.getGetAttributesResponse());  
901 - }  
902 - if (toSessionMsg.hasAttributeUpdateNotification()) {  
903 - listener.onAttributeUpdate(sessionId, toSessionMsg.getAttributeUpdateNotification());  
904 - }  
905 - if (toSessionMsg.hasSessionCloseNotification()) {  
906 - listener.onRemoteSessionCloseCommand(sessionId, toSessionMsg.getSessionCloseNotification());  
907 - }  
908 - if (toSessionMsg.hasToTransportUpdateCredentialsNotification()) {  
909 - listener.onToTransportUpdateCredentials(toSessionMsg.getToTransportUpdateCredentialsNotification());  
910 - }  
911 - if (toSessionMsg.hasToDeviceRequest()) {  
912 - listener.onToDeviceRpcRequest(sessionId, toSessionMsg.getToDeviceRequest());  
913 - }  
914 - if (toSessionMsg.hasToServerResponse()) {  
915 - String requestId = sessionId + "-" + toSessionMsg.getToServerResponse().getRequestId();  
916 - toServerRpcPendingMap.remove(requestId);  
917 - listener.onToServerRpcResponse(toSessionMsg.getToServerResponse());  
918 - }  
919 - });  
920 - if (md.getSessionType() == TransportProtos.SessionType.SYNC) {  
921 - deregisterSession(md.getSessionInfo()); 1226 + if (toSessionMsg.hasToDeviceRequest()) {
  1227 + listener.onToDeviceRpcRequest(sessionId, toSessionMsg.getToDeviceRequest());
922 } 1228 }
923 - } else {  
924 - log.trace("Processing broadcast notification: {}", toSessionMsg);  
925 - if (toSessionMsg.hasEntityUpdateMsg()) {  
926 - TransportProtos.EntityUpdateMsg msg = toSessionMsg.getEntityUpdateMsg();  
927 - EntityType entityType = EntityType.valueOf(msg.getEntityType());  
928 - if (EntityType.DEVICE_PROFILE.equals(entityType)) {  
929 - DeviceProfile deviceProfile = deviceProfileCache.put(msg.getData());  
930 - if (deviceProfile != null) {  
931 - log.info("On device profile update: {}", deviceProfile);  
932 - onProfileUpdate(deviceProfile);  
933 - }  
934 - } else if (EntityType.TENANT_PROFILE.equals(entityType)) {  
935 - rateLimitService.update(tenantProfileCache.put(msg.getData()));  
936 - } else if (EntityType.TENANT.equals(entityType)) {  
937 - Optional<Tenant> profileOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray());  
938 - if (profileOpt.isPresent()) {  
939 - Tenant tenant = profileOpt.get();  
940 - boolean updated = tenantProfileCache.put(tenant.getId(), tenant.getTenantProfileId());  
941 - if (updated) {  
942 - rateLimitService.update(tenant.getId());  
943 - }  
944 - }  
945 - } else if (EntityType.API_USAGE_STATE.equals(entityType)) {  
946 - Optional<ApiUsageState> stateOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray());  
947 - if (stateOpt.isPresent()) {  
948 - ApiUsageState apiUsageState = stateOpt.get();  
949 - rateLimitService.update(apiUsageState.getTenantId(), apiUsageState.isTransportEnabled());  
950 - //TODO: if transport is disabled, we should close all sessions and not to check credentials.  
951 - }  
952 - } else if (EntityType.DEVICE.equals(entityType)) {  
953 - Optional<Device> deviceOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray());  
954 - deviceOpt.ifPresent(device -> {  
955 - onDeviceUpdate(device);  
956 - eventPublisher.publishEvent(new DeviceUpdatedEvent(device));  
957 - });  
958 -  
959 - //Thingskit function  
960 - } else if (EntityType.JS_SCRIPT.equals(entityType)) {  
961 - Optional<TkDeviceScriptDTO> deviceOpt = dataDecodingEncodingService.decode(msg.getData().toByteArray());  
962 - deviceOpt.ifPresent(device -> {  
963 - eventPublisher.publishEvent(new ScriptUpdatedEvent(device));  
964 - });  
965 - }  
966 - } else if (toSessionMsg.hasEntityDeleteMsg()) {  
967 - TransportProtos.EntityDeleteMsg msg = toSessionMsg.getEntityDeleteMsg();  
968 - EntityType entityType = EntityType.valueOf(msg.getEntityType());  
969 - UUID entityUuid = new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB());  
970 - if (EntityType.DEVICE_PROFILE.equals(entityType)) {  
971 - deviceProfileCache.evict(new DeviceProfileId(new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB())));  
972 - } else if (EntityType.TENANT_PROFILE.equals(entityType)) {  
973 - tenantProfileCache.remove(new TenantProfileId(entityUuid));  
974 - } else if (EntityType.TENANT.equals(entityType)) {  
975 - rateLimitService.remove(TenantId.fromUUID(entityUuid));  
976 - } else if (EntityType.DEVICE.equals(entityType)) {  
977 - rateLimitService.remove(new DeviceId(entityUuid));  
978 - onDeviceDeleted(new DeviceId(entityUuid));  
979 - }  
980 - } else if (toSessionMsg.hasResourceUpdateMsg()) {  
981 - TransportProtos.ResourceUpdateMsg msg = toSessionMsg.getResourceUpdateMsg();  
982 - TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));  
983 - ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());  
984 - String resourceId = msg.getResourceKey();  
985 - transportResourceCache.update(tenantId, resourceType, resourceId);  
986 - sessions.forEach((id, mdRez) -> {  
987 - log.trace("ResourceUpdate - [{}] [{}]", id, mdRez);  
988 - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(msg));  
989 - });  
990 -  
991 - } else if (toSessionMsg.hasResourceDeleteMsg()) {  
992 - TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg();  
993 - TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));  
994 - ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());  
995 - String resourceId = msg.getResourceKey();  
996 - transportResourceCache.evict(tenantId, resourceType, resourceId);  
997 - sessions.forEach((id, mdRez) -> {  
998 - log.warn("ResourceDelete - [{}] [{}]", id, mdRez);  
999 - transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(msg));  
1000 - });  
1001 - } else {  
1002 - //TODO: should we notify the device actor about missed session?  
1003 - log.debug("[{}] Missing session.", sessionId); 1229 + if (toSessionMsg.hasToServerResponse()) {
  1230 + String requestId =
  1231 + sessionId + "-" + toSessionMsg.getToServerResponse().getRequestId();
  1232 + toServerRpcPendingMap.remove(requestId);
  1233 + listener.onToServerRpcResponse(toSessionMsg.getToServerResponse());
  1234 + }
  1235 + });
  1236 + if (md.getSessionType() == TransportProtos.SessionType.SYNC) {
  1237 + deregisterSession(md.getSessionInfo());
  1238 + }
  1239 + } else {
  1240 + log.trace("Processing broadcast notification: {}", toSessionMsg);
  1241 + if (toSessionMsg.hasEntityUpdateMsg()) {
  1242 + TransportProtos.EntityUpdateMsg msg = toSessionMsg.getEntityUpdateMsg();
  1243 + EntityType entityType = EntityType.valueOf(msg.getEntityType());
  1244 + if (EntityType.DEVICE_PROFILE.equals(entityType)) {
  1245 + DeviceProfile deviceProfile = deviceProfileCache.put(msg.getData());
  1246 + if (deviceProfile != null) {
  1247 + log.info("On device profile update: {}", deviceProfile);
  1248 + onProfileUpdate(deviceProfile);
  1249 + }
  1250 + } else if (EntityType.TENANT_PROFILE.equals(entityType)) {
  1251 + rateLimitService.update(tenantProfileCache.put(msg.getData()));
  1252 + } else if (EntityType.TENANT.equals(entityType)) {
  1253 + Optional<Tenant> profileOpt =
  1254 + dataDecodingEncodingService.decode(msg.getData().toByteArray());
  1255 + if (profileOpt.isPresent()) {
  1256 + Tenant tenant = profileOpt.get();
  1257 + boolean updated = tenantProfileCache.put(tenant.getId(), tenant.getTenantProfileId());
  1258 + if (updated) {
  1259 + rateLimitService.update(tenant.getId());
1004 } 1260 }
  1261 + }
  1262 + } else if (EntityType.API_USAGE_STATE.equals(entityType)) {
  1263 + Optional<ApiUsageState> stateOpt =
  1264 + dataDecodingEncodingService.decode(msg.getData().toByteArray());
  1265 + if (stateOpt.isPresent()) {
  1266 + ApiUsageState apiUsageState = stateOpt.get();
  1267 + rateLimitService.update(
  1268 + apiUsageState.getTenantId(), apiUsageState.isTransportEnabled());
  1269 + // TODO: if transport is disabled, we should close all sessions and not to check
  1270 + // credentials.
  1271 + }
  1272 + } else if (EntityType.DEVICE.equals(entityType)) {
  1273 + Optional<Device> deviceOpt =
  1274 + dataDecodingEncodingService.decode(msg.getData().toByteArray());
  1275 + deviceOpt.ifPresent(
  1276 + device -> {
  1277 + onDeviceUpdate(device);
  1278 + eventPublisher.publishEvent(new DeviceUpdatedEvent(device));
  1279 + });
  1280 +
  1281 + // Thingskit function
  1282 + } else if (EntityType.JS_SCRIPT.equals(entityType)) {
  1283 + Optional<TkDeviceScriptDTO> deviceOpt =
  1284 + dataDecodingEncodingService.decode(msg.getData().toByteArray());
  1285 + deviceOpt.ifPresent(
  1286 + device -> {
  1287 + eventPublisher.publishEvent(new ScriptUpdatedEvent(device));
  1288 + });
1005 } 1289 }
1006 - }  
1007 - 1290 + } else if (toSessionMsg.hasEntityDeleteMsg()) {
  1291 + TransportProtos.EntityDeleteMsg msg = toSessionMsg.getEntityDeleteMsg();
  1292 + EntityType entityType = EntityType.valueOf(msg.getEntityType());
  1293 + UUID entityUuid = new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB());
  1294 + if (EntityType.DEVICE_PROFILE.equals(entityType)) {
  1295 + deviceProfileCache.evict(
  1296 + new DeviceProfileId(new UUID(msg.getEntityIdMSB(), msg.getEntityIdLSB())));
  1297 + } else if (EntityType.TENANT_PROFILE.equals(entityType)) {
  1298 + tenantProfileCache.remove(new TenantProfileId(entityUuid));
  1299 + } else if (EntityType.TENANT.equals(entityType)) {
  1300 + rateLimitService.remove(TenantId.fromUUID(entityUuid));
  1301 + } else if (EntityType.DEVICE.equals(entityType)) {
  1302 + rateLimitService.remove(new DeviceId(entityUuid));
  1303 + onDeviceDeleted(new DeviceId(entityUuid));
  1304 + }
  1305 + } else if (toSessionMsg.hasResourceUpdateMsg()) {
  1306 + TransportProtos.ResourceUpdateMsg msg = toSessionMsg.getResourceUpdateMsg();
  1307 + TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));
  1308 + ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());
  1309 + String resourceId = msg.getResourceKey();
  1310 + transportResourceCache.update(tenantId, resourceType, resourceId);
  1311 + sessions.forEach(
  1312 + (id, mdRez) -> {
  1313 + log.trace("ResourceUpdate - [{}] [{}]", id, mdRez);
  1314 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceUpdate(msg));
  1315 + });
1008 1316
1009 - public void onProfileUpdate(DeviceProfile deviceProfile) {  
1010 - long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits();  
1011 - long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits();  
1012 - sessions.forEach((id, md) -> {  
1013 - //TODO: if transport types are different - we should close the session.  
1014 - if (md.getSessionInfo().getDeviceProfileIdMSB() == deviceProfileIdMSB  
1015 - && md.getSessionInfo().getDeviceProfileIdLSB() == deviceProfileIdLSB) {  
1016 - TransportProtos.SessionInfoProto newSessionInfo = TransportProtos.SessionInfoProto.newBuilder()  
1017 - .mergeFrom(md.getSessionInfo())  
1018 - .setDeviceProfileIdMSB(deviceProfileIdMSB)  
1019 - .setDeviceProfileIdLSB(deviceProfileIdLSB)  
1020 - .setDeviceType(deviceProfile.getName())  
1021 - .build();  
1022 - md.setSessionInfo(newSessionInfo);  
1023 - transportCallbackExecutor.submit(() -> md.getListener().onDeviceProfileUpdate(newSessionInfo, deviceProfile));  
1024 - } 1317 + } else if (toSessionMsg.hasResourceDeleteMsg()) {
  1318 + TransportProtos.ResourceDeleteMsg msg = toSessionMsg.getResourceDeleteMsg();
  1319 + TenantId tenantId = TenantId.fromUUID(new UUID(msg.getTenantIdMSB(), msg.getTenantIdLSB()));
  1320 + ResourceType resourceType = ResourceType.valueOf(msg.getResourceType());
  1321 + String resourceId = msg.getResourceKey();
  1322 + transportResourceCache.evict(tenantId, resourceType, resourceId);
  1323 + sessions.forEach(
  1324 + (id, mdRez) -> {
  1325 + log.warn("ResourceDelete - [{}] [{}]", id, mdRez);
  1326 + transportCallbackExecutor.submit(() -> mdRez.getListener().onResourceDelete(msg));
  1327 + });
  1328 + } else {
  1329 + // TODO: should we notify the device actor about missed session?
  1330 + log.debug("[{}] Missing session.", sessionId);
  1331 + }
  1332 + }
  1333 + }
  1334 +
  1335 + public void onProfileUpdate(DeviceProfile deviceProfile) {
  1336 + long deviceProfileIdMSB = deviceProfile.getId().getId().getMostSignificantBits();
  1337 + long deviceProfileIdLSB = deviceProfile.getId().getId().getLeastSignificantBits();
  1338 + sessions.forEach(
  1339 + (id, md) -> {
  1340 + // TODO: if transport types are different - we should close the session.
  1341 + if (md.getSessionInfo().getDeviceProfileIdMSB() == deviceProfileIdMSB
  1342 + && md.getSessionInfo().getDeviceProfileIdLSB() == deviceProfileIdLSB) {
  1343 + TransportProtos.SessionInfoProto newSessionInfo =
  1344 + TransportProtos.SessionInfoProto.newBuilder()
  1345 + .mergeFrom(md.getSessionInfo())
  1346 + .setDeviceProfileIdMSB(deviceProfileIdMSB)
  1347 + .setDeviceProfileIdLSB(deviceProfileIdLSB)
  1348 + .setDeviceType(deviceProfile.getName())
  1349 + .build();
  1350 + md.setSessionInfo(newSessionInfo);
  1351 + transportCallbackExecutor.submit(
  1352 + () -> md.getListener().onDeviceProfileUpdate(newSessionInfo, deviceProfile));
  1353 + }
1025 }); 1354 });
1026 - }  
1027 -  
1028 - private void onDeviceUpdate(Device device) {  
1029 - long deviceIdMSB = device.getId().getId().getMostSignificantBits();  
1030 - long deviceIdLSB = device.getId().getId().getLeastSignificantBits();  
1031 - long deviceProfileIdMSB = device.getDeviceProfileId().getId().getMostSignificantBits();  
1032 - long deviceProfileIdLSB = device.getDeviceProfileId().getId().getLeastSignificantBits();  
1033 - sessions.forEach((id, md) -> {  
1034 - if ((md.getSessionInfo().getDeviceIdMSB() == deviceIdMSB && md.getSessionInfo().getDeviceIdLSB() == deviceIdLSB)) {  
1035 - DeviceProfile newDeviceProfile;  
1036 - if (md.getSessionInfo().getDeviceProfileIdMSB() != deviceProfileIdMSB  
1037 - || md.getSessionInfo().getDeviceProfileIdLSB() != deviceProfileIdLSB) {  
1038 - //TODO: if transport types are different - we should close the session.  
1039 - newDeviceProfile = deviceProfileCache.get(new DeviceProfileId(new UUID(deviceProfileIdMSB, deviceProfileIdLSB)));  
1040 - } else {  
1041 - newDeviceProfile = null;  
1042 - }  
1043 - TransportProtos.SessionInfoProto newSessionInfo = TransportProtos.SessionInfoProto.newBuilder()  
1044 - .mergeFrom(md.getSessionInfo())  
1045 - .setDeviceProfileIdMSB(deviceProfileIdMSB)  
1046 - .setDeviceProfileIdLSB(deviceProfileIdLSB)  
1047 - .setDeviceName(device.getName())  
1048 - .setDeviceType(device.getType()).build();  
1049 - if (device.getAdditionalInfo().has("gateway")  
1050 - && device.getAdditionalInfo().get("gateway").asBoolean()  
1051 - && device.getAdditionalInfo().has(OVERWRITE_ACTIVITY_TIME)  
1052 - && device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).isBoolean()) {  
1053 - md.setOverwriteActivityTime(device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).asBoolean());  
1054 - }  
1055 - md.setSessionInfo(newSessionInfo);  
1056 - transportCallbackExecutor.submit(() -> md.getListener().onDeviceUpdate(newSessionInfo, device, Optional.ofNullable(newDeviceProfile))); 1355 + }
  1356 +
  1357 + private void onDeviceUpdate(Device device) {
  1358 + long deviceIdMSB = device.getId().getId().getMostSignificantBits();
  1359 + long deviceIdLSB = device.getId().getId().getLeastSignificantBits();
  1360 + long deviceProfileIdMSB = device.getDeviceProfileId().getId().getMostSignificantBits();
  1361 + long deviceProfileIdLSB = device.getDeviceProfileId().getId().getLeastSignificantBits();
  1362 + sessions.forEach(
  1363 + (id, md) -> {
  1364 + if ((md.getSessionInfo().getDeviceIdMSB() == deviceIdMSB
  1365 + && md.getSessionInfo().getDeviceIdLSB() == deviceIdLSB)) {
  1366 + DeviceProfile newDeviceProfile;
  1367 + if (md.getSessionInfo().getDeviceProfileIdMSB() != deviceProfileIdMSB
  1368 + || md.getSessionInfo().getDeviceProfileIdLSB() != deviceProfileIdLSB) {
  1369 + // TODO: if transport types are different - we should close the session.
  1370 + newDeviceProfile =
  1371 + deviceProfileCache.get(
  1372 + new DeviceProfileId(new UUID(deviceProfileIdMSB, deviceProfileIdLSB)));
  1373 + } else {
  1374 + newDeviceProfile = null;
  1375 + }
  1376 + TransportProtos.SessionInfoProto newSessionInfo =
  1377 + TransportProtos.SessionInfoProto.newBuilder()
  1378 + .mergeFrom(md.getSessionInfo())
  1379 + .setDeviceProfileIdMSB(deviceProfileIdMSB)
  1380 + .setDeviceProfileIdLSB(deviceProfileIdLSB)
  1381 + .setDeviceName(device.getName())
  1382 + .setDeviceType(device.getType())
  1383 + .build();
  1384 + if (device.getAdditionalInfo().has("gateway")
  1385 + && device.getAdditionalInfo().get("gateway").asBoolean()
  1386 + && device.getAdditionalInfo().has(OVERWRITE_ACTIVITY_TIME)
  1387 + && device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).isBoolean()) {
  1388 + md.setOverwriteActivityTime(
  1389 + device.getAdditionalInfo().get(OVERWRITE_ACTIVITY_TIME).asBoolean());
1057 } 1390 }
  1391 + md.setSessionInfo(newSessionInfo);
  1392 + transportCallbackExecutor.submit(
  1393 + () ->
  1394 + md.getListener()
  1395 + .onDeviceUpdate(
  1396 + newSessionInfo, device, Optional.ofNullable(newDeviceProfile)));
  1397 + }
1058 }); 1398 });
1059 - }  
1060 -  
1061 - private void onDeviceDeleted(DeviceId deviceId) {  
1062 - sessions.forEach((id, md) -> {  
1063 - DeviceId sessionDeviceId = new DeviceId(new UUID(md.getSessionInfo().getDeviceIdMSB(), md.getSessionInfo().getDeviceIdLSB()));  
1064 - if (sessionDeviceId.equals(deviceId)) {  
1065 - transportCallbackExecutor.submit(() -> {  
1066 - md.getListener().onDeviceDeleted(deviceId); 1399 + }
  1400 +
  1401 + private void onDeviceDeleted(DeviceId deviceId) {
  1402 + sessions.forEach(
  1403 + (id, md) -> {
  1404 + DeviceId sessionDeviceId =
  1405 + new DeviceId(
  1406 + new UUID(
  1407 + md.getSessionInfo().getDeviceIdMSB(), md.getSessionInfo().getDeviceIdLSB()));
  1408 + if (sessionDeviceId.equals(deviceId)) {
  1409 + transportCallbackExecutor.submit(
  1410 + () -> {
  1411 + md.getListener().onDeviceDeleted(deviceId);
1067 }); 1412 });
1068 - } 1413 + }
1069 }); 1414 });
  1415 + }
  1416 +
  1417 + protected UUID toSessionId(TransportProtos.SessionInfoProto sessionInfo) {
  1418 + return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB());
  1419 + }
  1420 +
  1421 + protected UUID getRoutingKey(TransportProtos.SessionInfoProto sessionInfo) {
  1422 + return new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB());
  1423 + }
  1424 +
  1425 + protected TenantId getTenantId(TransportProtos.SessionInfoProto sessionInfo) {
  1426 + return TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB()));
  1427 + }
  1428 +
  1429 + protected CustomerId getCustomerId(TransportProtos.SessionInfoProto sessionInfo) {
  1430 + long msb = sessionInfo.getCustomerIdMSB();
  1431 + long lsb = sessionInfo.getCustomerIdLSB();
  1432 + if (msb != 0 && lsb != 0) {
  1433 + return new CustomerId(new UUID(msb, lsb));
  1434 + } else {
  1435 + return new CustomerId(EntityId.NULL_UUID);
  1436 + }
  1437 + }
  1438 +
  1439 + protected DeviceId getDeviceId(TransportProtos.SessionInfoProto sessionInfo) {
  1440 + return new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));
  1441 + }
  1442 +
  1443 + private static TransportProtos.SessionEventMsg getSessionEventMsg(
  1444 + TransportProtos.SessionEvent event) {
  1445 + return TransportProtos.SessionEventMsg.newBuilder()
  1446 + .setSessionType(TransportProtos.SessionType.ASYNC)
  1447 + .setEvent(event)
  1448 + .build();
  1449 + }
  1450 +
  1451 + protected void sendToDeviceActor(
  1452 + TransportProtos.SessionInfoProto sessionInfo,
  1453 + TransportToDeviceActorMsg toDeviceActorMsg,
  1454 + TransportServiceCallback<Void> callback) {
  1455 + TopicPartitionInfo tpi =
  1456 + partitionService.resolve(
  1457 + ServiceType.TB_CORE, getTenantId(sessionInfo), getDeviceId(sessionInfo));
  1458 + if (log.isTraceEnabled()) {
  1459 + log.trace(
  1460 + "[{}][{}] Pushing to topic {} message {}",
  1461 + getTenantId(sessionInfo),
  1462 + getDeviceId(sessionInfo),
  1463 + tpi.getFullTopicName(),
  1464 + toDeviceActorMsg);
  1465 + }
  1466 + TransportTbQueueCallback transportTbQueueCallback =
  1467 + callback != null ? new TransportTbQueueCallback(callback) : null;
  1468 + tbCoreProducerStats.incrementTotal();
  1469 + StatsCallback wrappedCallback =
  1470 + new StatsCallback(transportTbQueueCallback, tbCoreProducerStats);
  1471 + tbCoreMsgProducer.send(
  1472 + tpi,
  1473 + new TbProtoQueueMsg<>(
  1474 + getRoutingKey(sessionInfo),
  1475 + ToCoreMsg.newBuilder().setToDeviceActorMsg(toDeviceActorMsg).build()),
  1476 + wrappedCallback);
  1477 + }
  1478 +
  1479 + private void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) {
  1480 + TopicPartitionInfo tpi =
  1481 + partitionService.resolve(
  1482 + ServiceType.TB_RULE_ENGINE, tbMsg.getQueueName(), tenantId, tbMsg.getOriginator());
  1483 + if (log.isTraceEnabled()) {
  1484 + log.trace(
  1485 + "[{}][{}] Pushing to topic {} message {}",
  1486 + tenantId,
  1487 + tbMsg.getOriginator(),
  1488 + tpi.getFullTopicName(),
  1489 + tbMsg);
  1490 + }
  1491 + ToRuleEngineMsg msg =
  1492 + ToRuleEngineMsg.newBuilder()
  1493 + .setTbMsg(TbMsg.toByteString(tbMsg))
  1494 + .setTenantIdMSB(tenantId.getId().getMostSignificantBits())
  1495 + .setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
  1496 + .build();
  1497 + ruleEngineProducerStats.incrementTotal();
  1498 + StatsCallback wrappedCallback = new StatsCallback(callback, ruleEngineProducerStats);
  1499 + ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), wrappedCallback);
  1500 + }
  1501 +
  1502 + private void sendToRuleEngine(
  1503 + TenantId tenantId,
  1504 + DeviceId deviceId,
  1505 + CustomerId customerId,
  1506 + TransportProtos.SessionInfoProto sessionInfo,
  1507 + JsonObject json,
  1508 + TbMsgMetaData metaData,
  1509 + SessionMsgType sessionMsgType,
  1510 + TbQueueCallback callback) {
  1511 + DeviceProfileId deviceProfileId =
  1512 + new DeviceProfileId(
  1513 + new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));
  1514 + DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId);
  1515 + RuleChainId ruleChainId;
  1516 + String queueName;
  1517 +
  1518 + if (deviceProfile == null) {
  1519 + log.warn("[{}] Device profile is null!", deviceProfileId);
  1520 + ruleChainId = null;
  1521 + queueName = ServiceQueue.MAIN;
  1522 + } else {
  1523 + ruleChainId = deviceProfile.getDefaultRuleChainId();
  1524 + String defaultQueueName = deviceProfile.getDefaultQueueName();
  1525 + queueName = defaultQueueName != null ? defaultQueueName : ServiceQueue.MAIN;
  1526 + }
  1527 +
  1528 + TbMsg tbMsg =
  1529 + TbMsg.newMsg(
  1530 + queueName,
  1531 + sessionMsgType.name(),
  1532 + deviceId,
  1533 + customerId,
  1534 + metaData,
  1535 + gson.toJson(json),
  1536 + ruleChainId,
  1537 + null);
  1538 + sendToRuleEngine(tenantId, tbMsg, callback);
  1539 + }
  1540 +
  1541 + private class TransportTbQueueCallback implements TbQueueCallback {
  1542 + private final TransportServiceCallback<Void> callback;
  1543 +
  1544 + private TransportTbQueueCallback(TransportServiceCallback<Void> callback) {
  1545 + this.callback = callback;
1070 } 1546 }
1071 1547
1072 - protected UUID toSessionId(TransportProtos.SessionInfoProto sessionInfo) {  
1073 - return new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB());  
1074 - }  
1075 -  
1076 - protected UUID getRoutingKey(TransportProtos.SessionInfoProto sessionInfo) {  
1077 - return new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB());  
1078 - }  
1079 -  
1080 - protected TenantId getTenantId(TransportProtos.SessionInfoProto sessionInfo) {  
1081 - return TenantId.fromUUID(new UUID(sessionInfo.getTenantIdMSB(), sessionInfo.getTenantIdLSB()));  
1082 - }  
1083 -  
1084 - protected CustomerId getCustomerId(TransportProtos.SessionInfoProto sessionInfo) {  
1085 - long msb = sessionInfo.getCustomerIdMSB();  
1086 - long lsb = sessionInfo.getCustomerIdLSB();  
1087 - if (msb != 0 && lsb != 0) {  
1088 - return new CustomerId(new UUID(msb, lsb));  
1089 - } else {  
1090 - return new CustomerId(EntityId.NULL_UUID);  
1091 - }  
1092 - }  
1093 -  
1094 - protected DeviceId getDeviceId(TransportProtos.SessionInfoProto sessionInfo) {  
1095 - return new DeviceId(new UUID(sessionInfo.getDeviceIdMSB(), sessionInfo.getDeviceIdLSB()));  
1096 - }  
1097 -  
1098 - private static TransportProtos.SessionEventMsg getSessionEventMsg(TransportProtos.SessionEvent event) {  
1099 - return TransportProtos.SessionEventMsg.newBuilder()  
1100 - .setSessionType(TransportProtos.SessionType.ASYNC)  
1101 - .setEvent(event).build();  
1102 - }  
1103 -  
1104 - protected void sendToDeviceActor(TransportProtos.SessionInfoProto sessionInfo, TransportToDeviceActorMsg toDeviceActorMsg, TransportServiceCallback<Void> callback) {  
1105 - TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, getTenantId(sessionInfo), getDeviceId(sessionInfo));  
1106 - if (log.isTraceEnabled()) {  
1107 - log.trace("[{}][{}] Pushing to topic {} message {}", getTenantId(sessionInfo), getDeviceId(sessionInfo), tpi.getFullTopicName(), toDeviceActorMsg);  
1108 - }  
1109 - TransportTbQueueCallback transportTbQueueCallback = callback != null ?  
1110 - new TransportTbQueueCallback(callback) : null;  
1111 - tbCoreProducerStats.incrementTotal();  
1112 - StatsCallback wrappedCallback = new StatsCallback(transportTbQueueCallback, tbCoreProducerStats);  
1113 - tbCoreMsgProducer.send(tpi,  
1114 - new TbProtoQueueMsg<>(getRoutingKey(sessionInfo),  
1115 - ToCoreMsg.newBuilder().setToDeviceActorMsg(toDeviceActorMsg).build()),  
1116 - wrappedCallback); 1548 + @Override
  1549 + public void onSuccess(TbQueueMsgMetadata metadata) {
  1550 + DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onSuccess(null));
1117 } 1551 }
1118 1552
1119 - private void sendToRuleEngine(TenantId tenantId, TbMsg tbMsg, TbQueueCallback callback) {  
1120 - TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_RULE_ENGINE, tbMsg.getQueueName(), tenantId, tbMsg.getOriginator());  
1121 - if (log.isTraceEnabled()) {  
1122 - log.trace("[{}][{}] Pushing to topic {} message {}", tenantId, tbMsg.getOriginator(), tpi.getFullTopicName(), tbMsg);  
1123 - }  
1124 - ToRuleEngineMsg msg = ToRuleEngineMsg.newBuilder().setTbMsg(TbMsg.toByteString(tbMsg))  
1125 - .setTenantIdMSB(tenantId.getId().getMostSignificantBits())  
1126 - .setTenantIdLSB(tenantId.getId().getLeastSignificantBits()).build();  
1127 - ruleEngineProducerStats.incrementTotal();  
1128 - StatsCallback wrappedCallback = new StatsCallback(callback, ruleEngineProducerStats);  
1129 - ruleEngineMsgProducer.send(tpi, new TbProtoQueueMsg<>(tbMsg.getId(), msg), wrappedCallback); 1553 + @Override
  1554 + public void onFailure(Throwable t) {
  1555 + DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t));
1130 } 1556 }
  1557 + }
1131 1558
1132 - private void sendToRuleEngine(TenantId tenantId, DeviceId deviceId, CustomerId customerId, TransportProtos.SessionInfoProto sessionInfo, JsonObject json,  
1133 - TbMsgMetaData metaData, SessionMsgType sessionMsgType, TbQueueCallback callback) {  
1134 - DeviceProfileId deviceProfileId = new DeviceProfileId(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB()));  
1135 - DeviceProfile deviceProfile = deviceProfileCache.get(deviceProfileId);  
1136 - RuleChainId ruleChainId;  
1137 - String queueName;  
1138 -  
1139 - if (deviceProfile == null) {  
1140 - log.warn("[{}] Device profile is null!", deviceProfileId);  
1141 - ruleChainId = null;  
1142 - queueName = ServiceQueue.MAIN;  
1143 - } else {  
1144 - ruleChainId = deviceProfile.getDefaultRuleChainId();  
1145 - String defaultQueueName = deviceProfile.getDefaultQueueName();  
1146 - queueName = defaultQueueName != null ? defaultQueueName : ServiceQueue.MAIN;  
1147 - } 1559 + private static class StatsCallback implements TbQueueCallback {
  1560 + private final TbQueueCallback callback;
  1561 + private final MessagesStats stats;
1148 1562
1149 - TbMsg tbMsg = TbMsg.newMsg(queueName, sessionMsgType.name(), deviceId, customerId, metaData, gson.toJson(json), ruleChainId, null);  
1150 - sendToRuleEngine(tenantId, tbMsg, callback); 1563 + private StatsCallback(TbQueueCallback callback, MessagesStats stats) {
  1564 + this.callback = callback;
  1565 + this.stats = stats;
1151 } 1566 }
1152 1567
1153 - private class TransportTbQueueCallback implements TbQueueCallback {  
1154 - private final TransportServiceCallback<Void> callback;  
1155 -  
1156 - private TransportTbQueueCallback(TransportServiceCallback<Void> callback) {  
1157 - this.callback = callback;  
1158 - }  
1159 -  
1160 - @Override  
1161 - public void onSuccess(TbQueueMsgMetadata metadata) {  
1162 - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onSuccess(null));  
1163 - }  
1164 -  
1165 - @Override  
1166 - public void onFailure(Throwable t) {  
1167 - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t));  
1168 - } 1568 + @Override
  1569 + public void onSuccess(TbQueueMsgMetadata metadata) {
  1570 + stats.incrementSuccessful();
  1571 + if (callback != null) callback.onSuccess(metadata);
1169 } 1572 }
1170 1573
1171 - private static class StatsCallback implements TbQueueCallback {  
1172 - private final TbQueueCallback callback;  
1173 - private final MessagesStats stats;  
1174 -  
1175 - private StatsCallback(TbQueueCallback callback, MessagesStats stats) {  
1176 - this.callback = callback;  
1177 - this.stats = stats;  
1178 - }  
1179 -  
1180 - @Override  
1181 - public void onSuccess(TbQueueMsgMetadata metadata) {  
1182 - stats.incrementSuccessful();  
1183 - if (callback != null)  
1184 - callback.onSuccess(metadata);  
1185 - }  
1186 -  
1187 - @Override  
1188 - public void onFailure(Throwable t) {  
1189 - stats.incrementFailed();  
1190 - if (callback != null)  
1191 - callback.onFailure(t);  
1192 - } 1574 + @Override
  1575 + public void onFailure(Throwable t) {
  1576 + stats.incrementFailed();
  1577 + if (callback != null) callback.onFailure(t);
1193 } 1578 }
  1579 + }
1194 1580
1195 - private class MsgPackCallback implements TbQueueCallback {  
1196 - private final AtomicInteger msgCount;  
1197 - private final TransportServiceCallback<Void> callback; 1581 + private class MsgPackCallback implements TbQueueCallback {
  1582 + private final AtomicInteger msgCount;
  1583 + private final TransportServiceCallback<Void> callback;
1198 1584
1199 - public MsgPackCallback(Integer msgCount, TransportServiceCallback<Void> callback) {  
1200 - this.msgCount = new AtomicInteger(msgCount);  
1201 - this.callback = callback;  
1202 - }  
1203 -  
1204 - @Override  
1205 - public void onSuccess(TbQueueMsgMetadata metadata) {  
1206 - if (msgCount.decrementAndGet() <= 0) {  
1207 - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onSuccess(null));  
1208 - }  
1209 - }  
1210 -  
1211 - @Override  
1212 - public void onFailure(Throwable t) {  
1213 - DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t));  
1214 - }  
1215 - }  
1216 -  
1217 - private class ApiStatsProxyCallback<T> implements TransportServiceCallback<T> {  
1218 - private final TenantId tenantId;  
1219 - private final CustomerId customerId;  
1220 - private final int dataPoints;  
1221 - private final TransportServiceCallback<T> callback;  
1222 -  
1223 - public ApiStatsProxyCallback(TenantId tenantId, CustomerId customerId, int dataPoints, TransportServiceCallback<T> callback) {  
1224 - this.tenantId = tenantId;  
1225 - this.customerId = customerId;  
1226 - this.dataPoints = dataPoints;  
1227 - this.callback = callback;  
1228 - }  
1229 -  
1230 - @Override  
1231 - public void onSuccess(T msg) {  
1232 - try {  
1233 - apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.TRANSPORT_MSG_COUNT, 1);  
1234 - apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.TRANSPORT_DP_COUNT, dataPoints);  
1235 - } finally {  
1236 - callback.onSuccess(msg);  
1237 - }  
1238 - }  
1239 -  
1240 - @Override  
1241 - public void onError(Throwable e) {  
1242 - callback.onError(e);  
1243 - } 1585 + public MsgPackCallback(Integer msgCount, TransportServiceCallback<Void> callback) {
  1586 + this.msgCount = new AtomicInteger(msgCount);
  1587 + this.callback = callback;
1244 } 1588 }
1245 1589
1246 @Override 1590 @Override
1247 - public ExecutorService getCallbackExecutor() {  
1248 - return transportCallbackExecutor; 1591 + public void onSuccess(TbQueueMsgMetadata metadata) {
  1592 + if (msgCount.decrementAndGet() <= 0) {
  1593 + DefaultTransportService.this.transportCallbackExecutor.submit(
  1594 + () -> callback.onSuccess(null));
  1595 + }
1249 } 1596 }
1250 1597
1251 @Override 1598 @Override
1252 - public boolean hasSession(TransportProtos.SessionInfoProto sessionInfo) {  
1253 - return sessions.containsKey(toSessionId(sessionInfo)); 1599 + public void onFailure(Throwable t) {
  1600 + DefaultTransportService.this.transportCallbackExecutor.submit(() -> callback.onError(t));
1254 } 1601 }
  1602 + }
1255 1603
1256 - @Override  
1257 - public void createGaugeStats(String statsName, AtomicInteger number) {  
1258 - statsFactory.createGauge(StatsType.TRANSPORT + "." + statsName, number);  
1259 - statsMap.put(statsName, number);  
1260 - } 1604 + private class ApiStatsProxyCallback<T> implements TransportServiceCallback<T> {
  1605 + private final TenantId tenantId;
  1606 + private final CustomerId customerId;
  1607 + private final int dataPoints;
  1608 + private final TransportServiceCallback<T> callback;
1261 1609
1262 - @Scheduled(fixedDelayString = "${transport.stats.print-interval-ms:60000}")  
1263 - public void printStats() {  
1264 - if (statsEnabled && !statsMap.isEmpty()) {  
1265 - String values = statsMap.entrySet().stream()  
1266 - .map(kv -> kv.getKey() + " [" + kv.getValue() + "]").collect(Collectors.joining(", "));  
1267 - log.info("Transport Stats: {}", values);  
1268 - } 1610 + public ApiStatsProxyCallback(
  1611 + TenantId tenantId,
  1612 + CustomerId customerId,
  1613 + int dataPoints,
  1614 + TransportServiceCallback<T> callback) {
  1615 + this.tenantId = tenantId;
  1616 + this.customerId = customerId;
  1617 + this.dataPoints = dataPoints;
  1618 + this.callback = callback;
1269 } 1619 }
1270 1620
1271 -  
1272 -  
1273 -  
1274 -  
1275 -  
1276 -  
1277 -  
1278 -  
1279 - //Thingskit function  
1280 @Override 1621 @Override
1281 - public List<ScriptProto> getScripts(ScriptProto msg) {  
1282 - TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =  
1283 - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportProtos.TransportApiRequestMsg.newBuilder().setScript(msg).build());  
1284 - try {  
1285 - TbProtoQueueMsg<TransportApiResponseMsg> response = transportApiRequestTemplate.send(protoMsg).get();  
1286 - return response.getValue().getScriptsResponseMsgList();  
1287 - } catch (InterruptedException | ExecutionException e) {  
1288 - throw new RuntimeException(e);  
1289 - } 1622 + public void onSuccess(T msg) {
  1623 + try {
  1624 + apiUsageClient.report(tenantId, customerId, ApiUsageRecordKey.TRANSPORT_MSG_COUNT, 1);
  1625 + apiUsageClient.report(
  1626 + tenantId, customerId, ApiUsageRecordKey.TRANSPORT_DP_COUNT, dataPoints);
  1627 + } finally {
  1628 + callback.onSuccess(msg);
  1629 + }
1290 } 1630 }
1291 1631
1292 - //thingskit  
1293 @Override 1632 @Override
1294 - public void process(TransportProtos.SessionInfoProto sessionInfo, TransportProtos.Gbt28181RequestMsg msg,  
1295 - TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback) {  
1296 - if (checkLimits(sessionInfo, msg, callback)) {  
1297 - TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =  
1298 - new TbProtoQueueMsg<>(UUID.randomUUID(), TransportApiRequestMsg.newBuilder().setGbt28181RequestMsg(msg).build());  
1299 -  
1300 - AsyncCallbackTemplate.withCallback(transportApiRequestTemplate.send(protoMsg), response -> {  
1301 - callback.onSuccess(response.getValue().getGbt28181ResponseMsg());  
1302 - }, callback::onError, transportCallbackExecutor);  
1303 - }  
1304 - } 1633 + public void onError(Throwable e) {
  1634 + callback.onError(e);
  1635 + }
  1636 + }
  1637 +
  1638 + @Override
  1639 + public ExecutorService getCallbackExecutor() {
  1640 + return transportCallbackExecutor;
  1641 + }
  1642 +
  1643 + @Override
  1644 + public boolean hasSession(TransportProtos.SessionInfoProto sessionInfo) {
  1645 + return sessions.containsKey(toSessionId(sessionInfo));
  1646 + }
  1647 +
  1648 + @Override
  1649 + public void createGaugeStats(String statsName, AtomicInteger number) {
  1650 + statsFactory.createGauge(StatsType.TRANSPORT + "." + statsName, number);
  1651 + statsMap.put(statsName, number);
  1652 + }
  1653 +
  1654 + @Scheduled(fixedDelayString = "${transport.stats.print-interval-ms:60000}")
  1655 + public void printStats() {
  1656 + if (statsEnabled && !statsMap.isEmpty()) {
  1657 + String values =
  1658 + statsMap.entrySet().stream()
  1659 + .map(kv -> kv.getKey() + " [" + kv.getValue() + "]")
  1660 + .collect(Collectors.joining(", "));
  1661 + log.info("Transport Stats: {}", values);
  1662 + }
  1663 + }
  1664 +
  1665 + // Thingskit function
  1666 + @Override
  1667 + public List<ScriptProto> getScripts(ScriptProto msg) {
  1668 + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =
  1669 + new TbProtoQueueMsg<>(
  1670 + UUID.randomUUID(),
  1671 + TransportProtos.TransportApiRequestMsg.newBuilder().setScript(msg).build());
  1672 + try {
  1673 + TbProtoQueueMsg<TransportApiResponseMsg> response =
  1674 + transportApiRequestTemplate.send(protoMsg).get();
  1675 + return response.getValue().getScriptsResponseMsgList();
  1676 + } catch (InterruptedException | ExecutionException e) {
  1677 + throw new RuntimeException(e);
  1678 + }
  1679 + }
  1680 +
  1681 + // thingskit
  1682 + @Override
  1683 + public void process(
  1684 + TransportProtos.SessionInfoProto sessionInfo,
  1685 + TransportProtos.Gbt28181RequestMsg msg,
  1686 + TransportServiceCallback<TransportProtos.Gbt28181ResponseMsg> callback) {
  1687 + if (checkLimits(sessionInfo, msg, callback)) {
  1688 + TbProtoQueueMsg<TransportApiRequestMsg> protoMsg =
  1689 + new TbProtoQueueMsg<>(
  1690 + UUID.randomUUID(),
  1691 + TransportApiRequestMsg.newBuilder().setGbt28181RequestMsg(msg).build());
  1692 +
  1693 + AsyncCallbackTemplate.withCallback(
  1694 + transportApiRequestTemplate.send(protoMsg),
  1695 + response -> {
  1696 + callback.onSuccess(response.getValue().getGbt28181ResponseMsg());
  1697 + },
  1698 + callback::onError,
  1699 + transportCallbackExecutor);
  1700 + }
  1701 + }
  1702 +
  1703 + @Override
  1704 + public List<TransportProtos.Gbt28181MediaServerMsg> freshGtb28181Media(
  1705 + TransportProtos.Gbt28181MediaServerMsg msg) {
  1706 + TbProtoQueueMsg<TransportProtos.TransportApiRequestMsg> protoMsg =
  1707 + new TbProtoQueueMsg<>(
  1708 + UUID.randomUUID(),
  1709 + TransportProtos.TransportApiRequestMsg.newBuilder()
  1710 + .setGbt28181MediaServerMsg(msg)
  1711 + .build());
  1712 + try {
  1713 + TbProtoQueueMsg<TransportApiResponseMsg> response =
  1714 + transportApiRequestTemplate.send(protoMsg).get();
  1715 + return response.getValue().getGbt28181MediaServerMsgList();
  1716 + } catch (InterruptedException | ExecutionException e) {
  1717 + throw new RuntimeException(e);
  1718 + }
  1719 + }
1305 } 1720 }
@@ -4,7 +4,6 @@ import java.util.*; @@ -4,7 +4,6 @@ import java.util.*;
4 import lombok.extern.slf4j.Slf4j; 4 import lombok.extern.slf4j.Slf4j;
5 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
7 -import org.thingsboard.server.common.data.yunteng.config.media.SipConfig;  
8 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; 7 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;
9 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 8 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
10 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; 9 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils;
@@ -16,7 +15,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio @@ -16,7 +15,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidatio
16 public class SSRCFactory { 15 public class SSRCFactory {
17 16
18 /** 播流最大并发个数 */ 17 /** 播流最大并发个数 */
19 - private static final Integer MAX_STREAM_COUNT = 10000; 18 + private static final Integer MAX_STREAM_COUNT = 300;
20 19
21 /** 播流最大并发个数 */ 20 /** 播流最大并发个数 */
22 private static final String SSRC_INFO_KEY = "TK_SSRC_INFO_"; 21 private static final String SSRC_INFO_KEY = "TK_SSRC_INFO_";
@@ -24,26 +23,29 @@ public class SSRCFactory { @@ -24,26 +23,29 @@ public class SSRCFactory {
24 private final String cacheName = FastIotConstants.MediaServerKey.MEDIA_SERVER_CACHE_NAME; 23 private final String cacheName = FastIotConstants.MediaServerKey.MEDIA_SERVER_CACHE_NAME;
25 @Autowired private CacheUtils cacheUtils; 24 @Autowired private CacheUtils cacheUtils;
26 25
27 - @Autowired private SipConfig sipConfig;  
28 -  
29 @Autowired private UserSetting userSetting; 26 @Autowired private UserSetting userSetting;
30 27
31 public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) { 28 public void initMediaServerSSRC(String mediaServerId, Set<String> usedSet) {
32 - String ssrcPrefix = sipConfig.getDomain().substring(3, 8);  
33 - String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;  
34 - Set<String> ssrcList = new HashSet<>();  
35 - for (int i = 1; i < MAX_STREAM_COUNT; i++) {  
36 - String ssrc = String.format("%s%04d", ssrcPrefix, i); 29 + Optional<String> sipDomain =
  30 + cacheUtils.get(FastIotConstants.CacheSipKey.TK_SIP_CACHE_NAME, mediaServerId);
  31 + sipDomain.ifPresent(
  32 + domain -> {
  33 + String ssrcPrefix = domain.substring(3, 8);
  34 + String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
  35 + Set<String> ssrcList = new HashSet<>();
  36 + for (int i = 1; i < MAX_STREAM_COUNT; i++) {
  37 + String ssrc = String.format("%s%04d", ssrcPrefix, i);
37 38
38 - if (null == usedSet || !usedSet.contains(ssrc)) {  
39 - ssrcList.add(ssrc);  
40 - }  
41 - }  
42 - if (cacheUtils.get(cacheName, redisKey).isPresent()) {  
43 - cacheUtils.invalidate(cacheName, redisKey);  
44 - }  
45 - // 把这10000个ssrc放入缓存  
46 - cacheUtils.put(cacheName, redisKey, ssrcList); 39 + if (null == usedSet || !usedSet.contains(ssrc)) {
  40 + ssrcList.add(ssrc);
  41 + }
  42 + }
  43 + if (cacheUtils.get(cacheName, redisKey).isPresent()) {
  44 + cacheUtils.invalidate(cacheName, redisKey);
  45 + }
  46 + // 把这10000个ssrc放入缓存
  47 + cacheUtils.put(cacheName, redisKey, ssrcList);
  48 + });
47 } 49 }
48 50
49 /** 51 /**
@@ -3,15 +3,13 @@ package org.thingsboard.server.dao.yunteng.factory; @@ -3,15 +3,13 @@ package org.thingsboard.server.dao.yunteng.factory;
3 import java.text.ParseException; 3 import java.text.ParseException;
4 import java.util.*; 4 import java.util.*;
5 import java.util.concurrent.ConcurrentHashMap; 5 import java.util.concurrent.ConcurrentHashMap;
6 -  
7 import lombok.RequiredArgsConstructor; 6 import lombok.RequiredArgsConstructor;
8 import lombok.extern.slf4j.Slf4j; 7 import lombok.extern.slf4j.Slf4j;
9 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Component;
  9 +import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;
10 import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; 10 import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO;
11 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.ChannelOnlineEvent; 11 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.ChannelOnlineEvent;
12 -import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.OnStreamChangedHookParam;  
13 import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; 12 import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils;
14 -import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;  
15 import org.thingsboard.server.dao.yunteng.service.media.TkCacheStorageService; 13 import org.thingsboard.server.dao.yunteng.service.media.TkCacheStorageService;
16 14
17 @Component 15 @Component
@@ -24,31 +22,36 @@ public class ZLMMediaListManager { @@ -24,31 +22,36 @@ public class ZLMMediaListManager {
24 private final ZLMRTPServerFactory zlmrtpServerFactory; 22 private final ZLMRTPServerFactory zlmrtpServerFactory;
25 private final TkCacheStorageService tkCacheStorageService; 23 private final TkCacheStorageService tkCacheStorageService;
26 private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>(); 24 private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>();
27 -// public StreamPushItem addPush(OnStreamChangedHookParam onStreamChangedHookParam) {  
28 -// StreamPushItem transform = streamPushService.transform(onStreamChangedHookParam);  
29 -// StreamPushItem pushInDb = streamPushService.getPush(onStreamChangedHookParam.getApp(), onStreamChangedHookParam.getStream());  
30 -// transform.setPushIng(onStreamChangedHookParam.isRegist());  
31 -// transform.setUpdateTime(DateUtil.getNow());  
32 -// transform.setPushTime(DateUtil.getNow());  
33 -// transform.setSelf(userSetting.getServerId().equals(onStreamChangedHookParam.getSeverId()));  
34 -// if (pushInDb == null) {  
35 -// transform.setCreateTime(DateUtil.getNow());  
36 -// streamPushMapper.add(transform);  
37 -// }else {  
38 -// streamPushMapper.update(transform);  
39 -// gbStreamMapper.updateMediaServer(onStreamChangedHookParam.getApp(), onStreamChangedHookParam.getStream(), onStreamChangedHookParam.getMediaServerId());  
40 -// }  
41 -// ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream());  
42 -// if ( channelOnlineEventLister != null) {  
43 -// try {  
44 -// channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());;  
45 -// } catch (ParseException e) {  
46 -// logger.error("addPush: ", e);  
47 -// }  
48 -// removedChannelOnlineEventLister(transform.getApp(), transform.getStream());  
49 -// }  
50 -// return transform;  
51 -// } 25 +
  26 + // public StreamPushItem addPush(OnStreamChangedHookParam onStreamChangedHookParam) {
  27 + // StreamPushItem transform = streamPushService.transform(onStreamChangedHookParam);
  28 + // StreamPushItem pushInDb = streamPushService.getPush(onStreamChangedHookParam.getApp(),
  29 + // onStreamChangedHookParam.getStream());
  30 + // transform.setPushIng(onStreamChangedHookParam.isRegist());
  31 + // transform.setUpdateTime(DateUtil.getNow());
  32 + // transform.setPushTime(DateUtil.getNow());
  33 + // transform.setSelf(userSetting.getServerId().equals(onStreamChangedHookParam.getSeverId()));
  34 + // if (pushInDb == null) {
  35 + // transform.setCreateTime(DateUtil.getNow());
  36 + // streamPushMapper.add(transform);
  37 + // }else {
  38 + // streamPushMapper.update(transform);
  39 + // gbStreamMapper.updateMediaServer(onStreamChangedHookParam.getApp(),
  40 + // onStreamChangedHookParam.getStream(), onStreamChangedHookParam.getMediaServerId());
  41 + // }
  42 + // ChannelOnlineEvent channelOnlineEventLister =
  43 + // getChannelOnlineEventLister(transform.getApp(), transform.getStream());
  44 + // if ( channelOnlineEventLister != null) {
  45 + // try {
  46 + // channelOnlineEventLister.run(transform.getApp(), transform.getStream(),
  47 + // transform.getServerId());;
  48 + // } catch (ParseException e) {
  49 + // logger.error("addPush: ", e);
  50 + // }
  51 + // removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
  52 + // }
  53 + // return transform;
  54 + // }
52 public void sendStreamEvent(String app, String stream, String mediaServerId) { 55 public void sendStreamEvent(String app, String stream, String mediaServerId) {
53 MediaServerDTO mediaServerItem = tkCacheStorageService.findInfoByMediaServerId(mediaServerId); 56 MediaServerDTO mediaServerItem = tkCacheStorageService.findInfoByMediaServerId(mediaServerId);
54 // 查看推流状态 57 // 查看推流状态
@@ -75,7 +75,8 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { @@ -75,7 +75,8 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService {
75 } 75 }
76 76
77 @Override 77 @Override
78 - public void closeRTPServer(MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback) { 78 + public void closeRTPServer(
  79 + MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback) {
79 if (mediaServerItem == null) { 80 if (mediaServerItem == null) {
80 callback.run(false); 81 callback.run(false);
81 return; 82 return;
@@ -85,13 +86,13 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { @@ -85,13 +86,13 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService {
85 86
86 @Override 87 @Override
87 public void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig) { 88 public void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig) {
  89 + String serverId = zlmServerConfig.getGeneralMediaServerId();
88 MediaServerDTO serverItem = 90 MediaServerDTO serverItem =
89 - tkMediaServerService.findMediaServerInfoById(  
90 - zlmServerConfig.getTenantId(), zlmServerConfig.getGeneralMediaServerId()); 91 + tkMediaServerService.findMediaServerInfoById(zlmServerConfig.getTenantId(), serverId);
91 if (serverItem == null) { 92 if (serverItem == null) {
92 log.warn( 93 log.warn(
93 "[未注册的zlm] 拒接接入:{}来自{}:{}", 94 "[未注册的zlm] 拒接接入:{}来自{}:{}",
94 - zlmServerConfig.getGeneralMediaServerId(), 95 + serverId,
95 zlmServerConfig.getIp(), 96 zlmServerConfig.getIp(),
96 zlmServerConfig.getHttpPort()); 97 zlmServerConfig.getHttpPort());
97 log.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致"); 98 log.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致");
@@ -99,7 +100,7 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { @@ -99,7 +100,7 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService {
99 } else { 100 } else {
100 log.info( 101 log.info(
101 "[ZLM] 正在连接 : {} -> {}:{}", 102 "[ZLM] 正在连接 : {} -> {}:{}",
102 - zlmServerConfig.getGeneralMediaServerId(), 103 + serverId,
103 zlmServerConfig.getIp(), 104 zlmServerConfig.getIp(),
104 zlmServerConfig.getHttpPort()); 105 zlmServerConfig.getHttpPort());
105 } 106 }
@@ -134,14 +135,14 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { @@ -134,14 +135,14 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService {
134 zlmServerConfig.getHttpPort()); 135 zlmServerConfig.getHttpPort());
135 return; 136 return;
136 } 137 }
137 - tkMediaServerService.saveOrUpdateMediaServer(serverItem); 138 + tkMediaServerService.updateMediaServer(serverItem);
138 String key = 139 String key =
139 FastIotConstants.MediaServerKey.MEDIA_SERVER_PREFIX 140 FastIotConstants.MediaServerKey.MEDIA_SERVER_PREFIX
140 + userSetting.getServerId() 141 + userSetting.getServerId()
141 + "_" 142 + "_"
142 - + zlmServerConfig.getGeneralMediaServerId(); 143 + + serverId;
143 if (ssrcFactory.hasMediaServerSSRC(serverItem.getMediaServerId())) { 144 if (ssrcFactory.hasMediaServerSSRC(serverItem.getMediaServerId())) {
144 - ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); 145 + ssrcFactory.initMediaServerSSRC(serverId, null);
145 } 146 }
146 cacheUtils.put(cacheName, key, serverItem); 147 cacheUtils.put(cacheName, key, serverItem);
147 resetOnlineServerItem(serverItem); 148 resetOnlineServerItem(serverItem);
@@ -161,12 +162,19 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService { @@ -161,12 +162,19 @@ public class TkMediaServerNodeServiceImpl implements TkMediaServerNodeService {
161 } 162 }
162 163
163 log.info( 164 log.info(
164 - "[ZLM] 连接成功 {} - {}:{} ",  
165 - zlmServerConfig.getGeneralMediaServerId(),  
166 - zlmServerConfig.getIp(),  
167 - zlmServerConfig.getHttpPort()); 165 + "[ZLM] 连接成功 {} - {}:{} ", serverId, zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
168 } 166 }
169 167
  168 + @Override
  169 + public void zlmServerOffline(String medisServerId) {
  170 + MediaServerDTO serverItem = tkMediaServerService.findMediaServerInfoById(null, medisServerId);
  171 + if (serverItem == null) {
  172 + log.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致");
  173 + return;
  174 + }
  175 + serverItem.setStatus(false);
  176 + tkMediaServerService.updateMediaServer(serverItem);
  177 + }
170 178
171 @Override 179 @Override
172 public void resetOnlineServerItem(MediaServerDTO mediaServerItem) { 180 public void resetOnlineServerItem(MediaServerDTO mediaServerItem) {
@@ -24,11 +24,8 @@ import org.thingsboard.server.common.data.id.EntityId; @@ -24,11 +24,8 @@ import org.thingsboard.server.common.data.id.EntityId;
24 import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager; 24 import org.thingsboard.server.common.data.yunteng.common.media.VideoStreamSessionManager;
25 import org.thingsboard.server.common.data.yunteng.common.media.ZlmHttpHookSubscribe; 25 import org.thingsboard.server.common.data.yunteng.common.media.ZlmHttpHookSubscribe;
26 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; 26 import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;
27 -import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig;  
28 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 27 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
29 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; 28 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils;
30 -import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;  
31 -import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;  
32 import org.thingsboard.server.common.data.yunteng.dto.sip.*; 29 import org.thingsboard.server.common.data.yunteng.dto.sip.*;
33 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherPsSendInfo; 30 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherPsSendInfo;
34 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherRtpSendInfo; 31 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.OtherRtpSendInfo;
@@ -111,7 +108,7 @@ public class TkMediaServerServiceImpl @@ -111,7 +108,7 @@ public class TkMediaServerServiceImpl
111 TkMediaServerEntity entity = 108 TkMediaServerEntity entity =
112 baseMapper.selectOne( 109 baseMapper.selectOne(
113 new LambdaQueryWrapper<TkMediaServerEntity>() 110 new LambdaQueryWrapper<TkMediaServerEntity>()
114 - .eq(TkMediaServerEntity::getTenantId, tenantId) 111 + // .eq(TkMediaServerEntity::getTenantId, tenantId)
115 .eq(TkMediaServerEntity::getMediaServerId, id)); 112 .eq(TkMediaServerEntity::getMediaServerId, id));
116 return Optional.ofNullable(entity).map(obj -> obj.getDTO(MediaServerDTO.class)).orElse(null); 113 return Optional.ofNullable(entity).map(obj -> obj.getDTO(MediaServerDTO.class)).orElse(null);
117 } 114 }
@@ -126,28 +123,24 @@ public class TkMediaServerServiceImpl @@ -126,28 +123,24 @@ public class TkMediaServerServiceImpl
126 } 123 }
127 124
128 @Override 125 @Override
129 - public MediaServerDTO saveOrUpdateMediaServer(MediaServerDTO mediaServer) { 126 + public MediaServerDTO saveMediaServer(MediaServerDTO mediaServer) {
130 TkMediaServerEntity entity = mediaServer.getEntity(TkMediaServerEntity.class); 127 TkMediaServerEntity entity = mediaServer.getEntity(TkMediaServerEntity.class);
131 - if (StringUtils.isEmpty(mediaServer.getId())) {  
132 - baseMapper.insert(entity);  
133 - } else {  
134 - TkMediaServerEntity queryEntity =  
135 - baseMapper.selectOne(  
136 - new LambdaQueryWrapper<TkMediaServerEntity>()  
137 - .eq(TkMediaServerEntity::getTenantId, mediaServer.getTenantId())  
138 - .eq(TkMediaServerEntity::getId, mediaServer.getId()));  
139 - if (null == queryEntity) {  
140 - throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());  
141 - }  
142 - baseMapper.updateById(entity);  
143 - }  
144 - return mediaServer; 128 + baseMapper.insert(entity);
  129 + return entity.getDTO(MediaServerDTO.class);
145 } 130 }
146 131
147 @Override 132 @Override
148 - public MediaServerDTO getMediaServerForMinimumLoad(String tenantId) { 133 + public MediaServerDTO updateMediaServer(MediaServerDTO mediaServer) {
  134 + TkMediaServerEntity entity = mediaServer.getEntity(TkMediaServerEntity.class);
  135 +
  136 + baseMapper.updateById(entity);
  137 + return entity.getDTO(MediaServerDTO.class);
  138 + }
  139 +
  140 + @Override
  141 + public MediaServerDTO getMediaServerForMinimumLoad(String sipId) {
149 // 先从缓存获取 142 // 先从缓存获取
150 - MediaServerDTO mediaServerDTO = tkCacheStorageService.findMediaServerForMinimumLoad(tenantId); 143 + MediaServerDTO mediaServerDTO = tkCacheStorageService.findMediaServerForMinimumLoad(sipId);
151 if (null != mediaServerDTO) { 144 if (null != mediaServerDTO) {
152 return mediaServerDTO; 145 return mediaServerDTO;
153 } else { 146 } else {
@@ -157,9 +150,9 @@ public class TkMediaServerServiceImpl @@ -157,9 +150,9 @@ public class TkMediaServerServiceImpl
157 } 150 }
158 151
159 @Override 152 @Override
160 - public MediaServerDTO getMediaServerForPlay(String tenantId, String mediaServerId) { 153 + public MediaServerDTO getMediaServerForPlay(String sipId, String mediaServerId) {
161 if (StringUtils.isEmpty(mediaServerId)) { 154 if (StringUtils.isEmpty(mediaServerId)) {
162 - return getMediaServerForMinimumLoad(tenantId); 155 + return getMediaServerForMinimumLoad(sipId);
163 } else { 156 } else {
164 return getMediaServerByMediaServerId(mediaServerId); 157 return getMediaServerByMediaServerId(mediaServerId);
165 } 158 }
@@ -595,7 +588,8 @@ public class TkMediaServerServiceImpl @@ -595,7 +588,8 @@ public class TkMediaServerServiceImpl
595 ret.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, playStream.getChannelId()); 588 ret.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, playStream.getChannelId());
596 ret.put(FastIotConstants.ZLMediaBody.CAMERA_CODE, playStream.getCameraCode()); 589 ret.put(FastIotConstants.ZLMediaBody.CAMERA_CODE, playStream.getCameraCode());
597 ret.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM, playStream.getStream()); 590 ret.put(FastIotConstants.ZLMediaBody.SSRCINFO_STREAM, playStream.getStream());
598 - tkCacheStorageService.deleteCacheStreamInfoByStopPlay(playStream); //redisCatchStorage.stopPlay(streamInfo); 591 + tkCacheStorageService.deleteCacheStreamInfoByStopPlay(
  592 + playStream); // redisCatchStorage.stopPlay(streamInfo);
599 }); 593 });
600 // 点播 594 // 点播
601 // 录像回放 595 // 录像回放
@@ -649,8 +643,9 @@ public class TkMediaServerServiceImpl @@ -649,8 +643,9 @@ public class TkMediaServerServiceImpl
649 643
650 @Override 644 @Override
651 public HookResult zlmOnServerKeepalive(OnServerKeepaliveHookParam param) { 645 public HookResult zlmOnServerKeepalive(OnServerKeepaliveHookParam param) {
652 - executorResponseAllSubscribeByHookTypeEnum(  
653 - HookTypeEnum.ON_SERVER_KEEPALIVE, JacksonUtil.convertValue(param, JsonNode.class), null); 646 + // executorResponseAllSubscribeByHookTypeEnum(
  647 + // HookTypeEnum.ON_SERVER_KEEPALIVE, JacksonUtil.convertValue(param, JsonNode.class),
  648 + // null);
654 // TODO 649 // TODO
655 return HookResult.SUCCESS(); 650 return HookResult.SUCCESS();
656 } 651 }
@@ -760,22 +755,22 @@ public class TkMediaServerServiceImpl @@ -760,22 +755,22 @@ public class TkMediaServerServiceImpl
760 return map; 755 return map;
761 } 756 }
762 757
763 - private void executorResponseAllSubscribeByHookTypeEnum(  
764 - HookTypeEnum HookTypeEnum, JsonNode jsonNode, ZLMediaKitServerConfig zlmServerConfig) {  
765 - // taskExecutor.execute(  
766 - // () -> {  
767 - // List<ZlmHttpHookSubscribe.Event> subscribes =  
768 - // this.subscribe.getSubscribes(HookTypeEnum);  
769 - // if (subscribes != null && subscribes.size() > 0) {  
770 - // for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {  
771 - // subscribe.response(null, jsonNode);  
772 - // }  
773 - // }  
774 - // if (null != zlmServerConfig) {  
775 - // zlmServerOnline(zlmServerConfig);  
776 - // }  
777 - // });  
778 - } 758 + // private void executorResponseAllSubscribeByHookTypeEnum(
  759 + // HookTypeEnum HookTypeEnum, JsonNode jsonNode, ZLMediaKitServerConfig zlmServerConfig) {
  760 + // taskExecutor.execute(
  761 + // () -> {
  762 + // List<ZlmHttpHookSubscribe.Event> subscribes =
  763 + // this.subscribe.getSubscribes(HookTypeEnum);
  764 + // if (subscribes != null && subscribes.size() > 0) {
  765 + // for (ZlmHttpHookSubscribe.Event subscribe : subscribes) {
  766 + // subscribe.response(null, jsonNode);
  767 + // }
  768 + // }
  769 + // if (null != zlmServerConfig) {
  770 + // zlmServerOnline(zlmServerConfig);
  771 + // }
  772 + // });
  773 + // }
779 774
780 private HookResultForOnPublish appIsNotRtp(BaseParam param, MediaServerDTO mediaInfo) { 775 private HookResultForOnPublish appIsNotRtp(BaseParam param, MediaServerDTO mediaInfo) {
781 // HookResultForOnPublish hookResultForOnPublish = new HookResultForOnPublish(401, 776 // HookResultForOnPublish hookResultForOnPublish = new HookResultForOnPublish(401,
@@ -60,6 +60,7 @@ public interface TkCacheStorageService { @@ -60,6 +60,7 @@ public interface TkCacheStorageService {
60 * @param tenantId 租户ID 60 * @param tenantId 租户ID
61 * @return 流媒体信息 61 * @return 流媒体信息
62 */ 62 */
  63 + @Deprecated
63 MediaServerDTO findMediaServerForMinimumLoad(String tenantId); 64 MediaServerDTO findMediaServerForMinimumLoad(String tenantId);
64 65
65 /** 66 /**
1 package org.thingsboard.server.dao.yunteng.service.media; 1 package org.thingsboard.server.dao.yunteng.service.media;
2 2
3 import java.util.Optional; 3 import java.util.Optional;
4 -  
5 import org.thingsboard.server.common.data.yunteng.common.media.CommonCallback; 4 import org.thingsboard.server.common.data.yunteng.common.media.CommonCallback;
6 import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig; 5 import org.thingsboard.server.common.data.yunteng.config.media.ZLMediaKitServerConfig;
7 import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; 6 import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO;
@@ -20,10 +19,23 @@ public interface TkMediaServerNodeService { @@ -20,10 +19,23 @@ public interface TkMediaServerNodeService {
20 /** zlm 重启后重置他的推流信息 */ 19 /** zlm 重启后重置他的推流信息 */
21 void clearRTPServer(MediaServerDTO mediaServerItem); 20 void clearRTPServer(MediaServerDTO mediaServerItem);
22 21
23 - void closeRTPServer(MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback); 22 + void closeRTPServer(
  23 + MediaServerDTO mediaServerItem, String streamId, CommonCallback<Boolean> callback);
24 24
  25 + /**
  26 + * 处理zlm上线
  27 + *
  28 + * @param zlmServerConfig ZLM返回的流媒体配置
  29 + */
25 void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig); 30 void zlmServerOnline(ZLMediaKitServerConfig zlmServerConfig);
26 31
  32 + /**
  33 + * 处理zlm上线
  34 + *
  35 + * @param mediaServerId ZLM返回的流媒体配置
  36 + */
  37 + void zlmServerOffline(String mediaServerId);
  38 +
27 void resetOnlineServerItem(MediaServerDTO mediaServerItem); 39 void resetOnlineServerItem(MediaServerDTO mediaServerItem);
28 40
29 /** 41 /**
1 package org.thingsboard.server.dao.yunteng.service.media; 1 package org.thingsboard.server.dao.yunteng.service.media;
2 2
3 import com.fasterxml.jackson.databind.JsonNode; 3 import com.fasterxml.jackson.databind.JsonNode;
  4 +import java.util.List;
4 import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO; 5 import org.thingsboard.server.common.data.yunteng.dto.sip.MediaServerDTO;
5 import org.thingsboard.server.common.data.yunteng.dto.sip.StreamInfoDTO; 6 import org.thingsboard.server.common.data.yunteng.dto.sip.StreamInfoDTO;
6 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*; 7 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.*;
7 8
8 -import java.util.List;  
9 -  
10 public interface TkMediaServerService { 9 public interface TkMediaServerService {
11 10
12 /** 11 /**
@@ -15,6 +14,7 @@ public interface TkMediaServerService { @@ -15,6 +14,7 @@ public interface TkMediaServerService {
15 * @return 流媒体列表 14 * @return 流媒体列表
16 */ 15 */
17 List<MediaServerDTO> getAllMediaKit(); 16 List<MediaServerDTO> getAllMediaKit();
  17 +
18 /** 18 /**
19 * 通过流媒体ID获取流媒体信息 19 * 通过流媒体ID获取流媒体信息
20 * 20 *
@@ -37,7 +37,15 @@ public interface TkMediaServerService { @@ -37,7 +37,15 @@ public interface TkMediaServerService {
37 * @param mediaServer 流媒体信息 37 * @param mediaServer 流媒体信息
38 * @return 流媒体信息 38 * @return 流媒体信息
39 */ 39 */
40 - MediaServerDTO saveOrUpdateMediaServer(MediaServerDTO mediaServer); 40 + MediaServerDTO saveMediaServer(MediaServerDTO mediaServer);
  41 +
  42 + /**
  43 + * 刷新流媒体信息
  44 + *
  45 + * @param mediaServer 流媒体信息
  46 + * @return 流媒体信息
  47 + */
  48 + MediaServerDTO updateMediaServer(MediaServerDTO mediaServer);
41 49
42 /** 50 /**
43 * 获取当前租户最小负载的流媒体 51 * 获取当前租户最小负载的流媒体
@@ -45,6 +53,7 @@ public interface TkMediaServerService { @@ -45,6 +53,7 @@ public interface TkMediaServerService {
45 * @param tenantId 租户ID 53 * @param tenantId 租户ID
46 * @return 流媒体信息 54 * @return 流媒体信息
47 */ 55 */
  56 + @Deprecated
48 MediaServerDTO getMediaServerForMinimumLoad(String tenantId); 57 MediaServerDTO getMediaServerForMinimumLoad(String tenantId);
49 58
50 /** 59 /**
  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,5 +40,7 @@
40 <module>coap</module> 40 <module>coap</module>
41 <module>lwm2m</module> 41 <module>lwm2m</module>
42 <module>snmp</module> 42 <module>snmp</module>
  43 + <module>tcp</module>
  44 + <module>gbt28181</module>
43 </modules> 45 </modules>
44 </project> 46 </project>
  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,58 +119,49 @@ js:
119 enabled: "${TB_JS_REMOTE_STATS_ENABLED:false}" 119 enabled: "${TB_JS_REMOTE_STATS_ENABLED:false}"
120 print_interval_ms: "${TB_JS_REMOTE_STATS_PRINT_INTERVAL_MS:10000}" 120 print_interval_ms: "${TB_JS_REMOTE_STATS_PRINT_INTERVAL_MS:10000}"
121 121
122 -# GBT28181_ server parameters 122 +# GBT28181 server parameters
123 transport: 123 transport:
124 gbt28181: 124 gbt28181:
125 - bind_address: "${TCP_BIND_ADDRESS:0.0.0.0}"  
126 - bind_port: "${TCP_BIND_PORT:8088}"  
127 - # Enable proxy protocol support. Disabled by default. If enabled, supports both v1 and v2.  
128 - # Useful to get the real IP address of the client in the logs and for rate limits.  
129 - proxy_enabled: "${TCP_PROXY_PROTOCOL_ENABLED:false}"  
130 - timeout: "${TCP_TIMEOUT:10000}"  
131 - msg_queue_size_per_device_limit: "${TCP_MSG_QUEUE_SIZE_PER_DEVICE_LIMIT:100}" # messages await in the queue before device connected state. This limit works on low level before TenantProfileLimits mechanism  
132 - netty:  
133 - leak_detector_level: "${NETTY_LEAK_DETECTOR_LVL:DISABLED}"  
134 - boss_group_thread_count: "${NETTY_BOSS_GROUP_THREADS:1}"  
135 - worker_group_thread_count: "${NETTY_WORKER_GROUP_THREADS:12}"  
136 - max_payload_size: "${NETTY_MAX_PAYLOAD_SIZE:65536}"  
137 - so_keep_alive: "${NETTY_SO_KEEPALIVE:false}"  
138 - # TCP_ SSL configuration  
139 - ssl:  
140 - # Enable/disable SSL support  
141 - enabled: "${TCP_SSL_ENABLED:false}"  
142 - # TCP_ SSL bind address  
143 - bind_address: "${TCP_SSL_BIND_ADDRESS:0.0.0.0}"  
144 - # TCP_ SSL bind port  
145 - bind_port: "${TCP_SSL_BIND_PORT:8883}"  
146 - # SSL protocol: See https://docs.oracle.com/en/java/javase/11/docs/specs/security/standard-names.html#sslcontext-algorithms  
147 - protocol: "${TCP_SSL_PROTOCOL:TLSv1.2}"  
148 - # Server SSL credentials  
149 - credentials:  
150 - # Server credentials type (PEM - pem certificate file; KEYSTORE - java keystore)  
151 - type: "${TCP_SSL_CREDENTIALS_TYPE:PEM}"  
152 - # PEM server credentials  
153 - pem:  
154 - # Path to the server certificate file (holds server certificate or certificate chain, may include server private key)  
155 - cert_file: "${TCP_SSL_PEM_CERT:tcpserver.pem}"  
156 - # Path to the server certificate private key file. Optional by default. Required if the private key is not present in server certificate file;  
157 - key_file: "${TCP_SSL_PEM_KEY:tcpserver_key.pem}"  
158 - # Server certificate private key password (optional)  
159 - key_password: "${TCP_SSL_PEM_KEY_PASSWORD:server_key_password}"  
160 - # Keystore server credentials  
161 - keystore:  
162 - # Type of the key store  
163 - type: "${TCP_SSL_KEY_STORE_TYPE:JKS}"  
164 - # Path to the key store that holds the SSL certificate  
165 - store_file: "${TCP_SSL_KEY_STORE:tcpserver.jks}"  
166 - # Password used to access the key store  
167 - store_password: "${TCP_SSL_KEY_STORE_PASSWORD:server_ks_password}"  
168 - # Optional alias of the private key; If not set, the platform will load the first private key from the keystore;  
169 - key_alias: "${TCP_SSL_KEY_ALIAS:}"  
170 - # Password used to access the key  
171 - key_password: "${TCP_SSL_KEY_PASSWORD:server_key_password}"  
172 - # Skip certificate validity check for client certificates.  
173 - skip_validity_check_for_client_cert: "${TCP_SSL_SKIP_VALIDITY_CHECK_FOR_CLIENT_CERT:false}" 125 + sip:
  126 + # [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
  127 + # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
  128 + # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
  129 + # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
  130 + ip: ${GBT28181_SIP_IP:127.0.0.1}
  131 + # [可选] 28181服务监听的端口
  132 + port: ${GBT28181_SIP_PORT:5060}
  133 + #[可选]
  134 + id: ${GBT28181_SIP_ID:51010700599000000001}
  135 + # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
  136 + # 后两位为行业编码,定义参照附录D.3
  137 + # 3701020049标识山东济南历下区 信息行业接入
  138 + # [可选]
  139 + domain: ${GBT28181_SIP_DOMAIN:5101070059}
  140 + #[可选]
  141 + password: ${GBT28181_SIP_PASSWORD:61332286}
  142 + #zlm 默认服务器配置
  143 + media:
  144 + id: ${GBT28181_MEDIA_GENERAL_ID:D2okJWKKaQ5bX7Va}
  145 + # [必须修改] zlm服务器的内网IP
  146 + ip: ${GBT28181_MEDIA_IP:127.0.0.1}
  147 + # [必须修改] zlm服务器的http.port
  148 + http-port: ${GBT28181_MEDIA_HTTP_PORT:28080}
  149 + hook-ip: ${GBT28181_MEDIA_HOOK_IP:}
  150 + stream-ip: ${GBT28181_MEDIA_STREAM_IP:}
  151 + # [可选] zlm服务器的hook.admin_params=secret
  152 + secret: ${GBT28181_MEDIA_API_SECRET:QhrTN7k6HcDnt0YyeolwHwiVYDgIHPMZ}
  153 + # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
  154 + rtp:
  155 + # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
  156 + enable: true
  157 + # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
  158 + port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围
  159 + # [可选] 国标级联在此范围内选择端口发送媒体流,
  160 + send-port-range: ${GBT28181_MEDIA_RTP_PORT_RANGE:30000,30500} # 端口范围
  161 + # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
  162 + record-assist-port: 0
  163 + defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:10}"
  164 +
174 sessions: 165 sessions:
175 inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" 166 inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}"
176 report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:3000}" 167 report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:3000}"