Added ability to provision credentials type from device using provision feature

This commit is contained in:
zbeacon 2020-10-08 15:08:29 +03:00
parent 5dd460b81d
commit adf5069da1
15 changed files with 165 additions and 48 deletions

View File

@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration;
import org.thingsboard.server.common.data.device.profile.CheckPreProvisionedDevicesDeviceProfileProvisionConfiguration;
import org.thingsboard.server.common.data.id.CustomerId;
@ -118,6 +119,13 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService {
return Futures.immediateFuture(new ProvisionResponse(null, ProvisionResponseStatus.NOT_FOUND));
}
if (provisionRequest.getCredentialsType() != null) {
ListenableFuture<ProvisionResponse> error = validateCredentials(provisionRequest);
if (error != null) {
return error;
}
}
DeviceProfile targetProfile = deviceProfileDao.findByProvisionDeviceKey(provisionRequestKey);
if (targetProfile == null) {
@ -152,6 +160,32 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService {
return Futures.immediateFuture(new ProvisionResponse(null, ProvisionResponseStatus.NOT_FOUND));
}
private ListenableFuture<ProvisionResponse> validateCredentials(ProvisionRequest provisionRequest) {
switch (provisionRequest.getCredentialsType()) {
case ACCESS_TOKEN:
if (StringUtils.isEmpty(provisionRequest.getCredentialsData().getToken())) {
log.error("Failed to get token from credentials data!");
return Futures.immediateFuture(new ProvisionResponse(null, ProvisionResponseStatus.FAILURE));
}
break;
case MQTT_BASIC:
if (StringUtils.isEmpty(provisionRequest.getCredentialsData().getClientId()) ||
StringUtils.isEmpty(provisionRequest.getCredentialsData().getUsername()) ||
StringUtils.isEmpty(provisionRequest.getCredentialsData().getPassword())) {
log.error("Failed to get basic mqtt credentials from credentials data!");
return Futures.immediateFuture(new ProvisionResponse(null, ProvisionResponseStatus.FAILURE));
}
break;
case X509_CERTIFICATE:
if (StringUtils.isEmpty(provisionRequest.getCredentialsData().getHash())) {
log.error("Failed to get hash from credentials data!");
return Futures.immediateFuture(new ProvisionResponse(null, ProvisionResponseStatus.FAILURE));
}
break;
}
return null;
}
private ListenableFuture<ProvisionResponse> processProvision(Device device, ProvisionRequest provisionRequest) {
ListenableFuture<Optional<AttributeKvEntry>> provisionStateFuture = attributesService.find(device.getTenantId(), device.getId(),
DataConstants.SERVER_SCOPE, DEVICE_PROVISION_STATE);
@ -205,7 +239,7 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService {
return Futures.transform(saveProvisionStateAttribute(savedDevice), input ->
new ProvisionResponse(
getDeviceCredentials(savedDevice, provisionRequest.getX509CertPubKey()),
getDeviceCredentials(savedDevice),
ProvisionResponseStatus.SUCCESS), MoreExecutors.directExecutor());
}
log.warn("[{}] The device is already provisioned!", device.getName());
@ -224,17 +258,33 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService {
device.setName(provisionRequest.getDeviceName());
device.setType(profile.getName());
device.setTenantId(profile.getTenantId());
return deviceService.saveDevice(device);
Device savedDevice = deviceService.saveDevice(device);
if (provisionRequest.getCredentialsType() != null) {
DeviceCredentials deviceCredentials = new DeviceCredentials();
deviceCredentials.setCredentialsType(provisionRequest.getCredentialsType());
switch (provisionRequest.getCredentialsType()) {
case ACCESS_TOKEN:
deviceCredentials.setDeviceId(savedDevice.getId());
deviceCredentials.setCredentialsId(provisionRequest.getCredentialsData().getToken());
break;
case MQTT_BASIC:
BasicMqttCredentials mqttCredentials = new BasicMqttCredentials();
mqttCredentials.setClientId(provisionRequest.getCredentialsData().getClientId());
mqttCredentials.setUserName(provisionRequest.getCredentialsData().getUsername());
mqttCredentials.setPassword(provisionRequest.getCredentialsData().getPassword());
deviceCredentials.setCredentialsValue(JacksonUtil.toString(mqttCredentials));
break;
case X509_CERTIFICATE:
deviceCredentials.setCredentialsValue(provisionRequest.getCredentialsData().getHash());
break;
}
deviceCredentialsService.updateDeviceCredentials(savedDevice.getTenantId(), deviceCredentials);
}
return savedDevice;
}
private DeviceCredentials getDeviceCredentials(Device device, String x509CertPubKey) {
DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId());
if (!StringUtils.isEmpty(x509CertPubKey)) {
credentials.setCredentialsType(DeviceCredentialsType.X509_CERTIFICATE);
credentials.setCredentialsValue(x509CertPubKey);
return deviceCredentialsService.updateDeviceCredentials(device.getTenantId(), credentials);
}
return credentials;
private DeviceCredentials getDeviceCredentials(Device device) {
return deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId());
}
private void pushProvisionEventToRuleEngine(ProvisionRequest request, Device device, String type) {

View File

@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData;
import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
@ -281,7 +282,12 @@ public class DefaultTransportApiService implements TransportApiService {
provisionResponseFuture = deviceProvisionService.provisionDevice(
new ProvisionRequest(
requestMsg.getDeviceName(),
requestMsg.getX509CertPubKey(),
requestMsg.getCredentialsType() != null ? DeviceCredentialsType.valueOf(requestMsg.getCredentialsType().name()) : null,
new ProvisionDeviceCredentialsData(requestMsg.getCredentialsDataProto().getValidateDeviceTokenRequestMsg().getToken(),
requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getClientId(),
requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getUserName(),
requestMsg.getCredentialsDataProto().getValidateBasicMqttCredRequestMsg().getPassword(),
requestMsg.getCredentialsDataProto().getValidateDeviceX509CertRequestMsg().getHash()),
new ProvisionDeviceProfileCredentials(
requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceKey(),
requestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceSecret())));

View File

@ -183,7 +183,7 @@ public abstract class AbstractMqttProvisionProtoDeviceTest extends AbstractMqttI
protected byte[] createTestProvisionMessage() {
return ProvisionDeviceRequestMsg.newBuilder().setX509CertPubKey("").setDeviceName("Test Provision device").setProvisionDeviceCredentialsMsg(ProvisionDeviceCredentialsMsg.newBuilder().setProvisionDeviceKey("testProvisionKey").setProvisionDeviceSecret("testProvisionSecret")).build().toByteArray();
return ProvisionDeviceRequestMsg.newBuilder().setDeviceName("Test Provision device").setProvisionDeviceCredentialsMsg(ProvisionDeviceCredentialsMsg.newBuilder().setProvisionDeviceKey("testProvisionKey").setProvisionDeviceSecret("testProvisionSecret")).build().toByteArray();
}
}

View File

@ -17,12 +17,15 @@ package org.thingsboard.server.dao.device.provision;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.thingsboard.server.common.data.device.credentials.ProvisionDeviceCredentialsData;
import org.thingsboard.server.common.data.device.profile.ProvisionDeviceProfileCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
@Data
@AllArgsConstructor
public class ProvisionRequest {
private String deviceName;
private String x509CertPubKey;
private DeviceCredentialsType credentialsType;
private ProvisionDeviceCredentialsData credentialsData;
private ProvisionDeviceProfileCredentials credentials;
}

View File

@ -79,5 +79,11 @@ public class DataConstants {
public static final String DEVICE_NAME = "deviceName";
public static final String DEVICE_TYPE = "deviceType";
public static final String CERT_PUB_KEY = "x509CertPubKey";
public static final String CREDENTIALS_TYPE = "credentialsType";
public static final String TOKEN = "token";
public static final String HASH = "hash";
public static final String CLIENT_ID = "clientId";
public static final String USERNAME = "username";
public static final String PASSWORD = "password";
}

View File

@ -0,0 +1,27 @@
/**
* Copyright © 2016-2020 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.device.credentials;
import lombok.Data;
@Data
public class ProvisionDeviceCredentialsData {
private final String token;
private final String clientId;
private final String username;
private final String password;
private final String hash;
}

View File

@ -68,8 +68,6 @@ public class MqttTopics {
public static final String GATEWAY_RPC_TOPIC = BASE_GATEWAY_API_TOPIC + RPC;
public static final String GATEWAY_ATTRIBUTES_REQUEST_TOPIC = BASE_GATEWAY_API_TOPIC + ATTRIBUTES_REQUEST;
public static final String GATEWAY_ATTRIBUTES_RESPONSE_TOPIC = BASE_GATEWAY_API_TOPIC + ATTRIBUTES_RESPONSE;
public static final String GATEWAY_PROVISION_REQUEST_TOPIC = BASE_GATEWAY_API_TOPIC + PROVISION + REQUEST;
public static final String GATEWAY_PROVISION_RESPONSE_TOPIC = BASE_GATEWAY_API_TOPIC + PROVISION + RESPONSE;
private MqttTopics() {
}

View File

@ -76,6 +76,7 @@ enum KeyValueType {
enum CredentialsType {
ACCESS_TOKEN = 0;
X509_CERTIFICATE = 1;
BASIC_MQTT = 2;
}
message KeyValueProto {
@ -254,10 +255,22 @@ message DeviceCredentialsProto {
string credentialsValue = 5;
}
message CredentialsDataProto {
ValidateDeviceTokenRequestMsg validateDeviceTokenRequestMsg = 1;
ValidateDeviceX509CertRequestMsg validateDeviceX509CertRequestMsg = 2;
ValidateBasicMqttCredRequestMsg validateBasicMqttCredRequestMsg = 3;
}
message ProvisionDeviceRequestMsg {
string deviceName = 1;
string x509CertPubKey = 2;
CredentialsType credentialsType = 2;
ProvisionDeviceCredentialsMsg provisionDeviceCredentialsMsg = 3;
CredentialsDataProto credentialsDataProto = 4;
}
message GatewayProvisionRequestMsg {
int32 requestId = 1;
ProvisionDeviceRequestMsg provisionDeviceRequestMsg = 2;
}
message ProvisionDeviceCredentialsMsg {
@ -270,6 +283,11 @@ message ProvisionDeviceResponseMsg {
ProvisionResponseStatus provisionResponseStatus = 2;
}
message GatewayProvisionResponseMsg {
int32 requestId = 1;
ProvisionDeviceResponseMsg provisionDeviceResponseMsg = 2;
}
enum ProvisionResponseStatus {
UNKNOWN = 0;
SUCCESS = 1;

View File

@ -17,7 +17,6 @@ package org.thingsboard.server.transport.mqtt;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSyntaxException;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.mqtt.MqttConnAckMessage;
@ -70,11 +69,10 @@ import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_ACCEPTED;
import static io.netty.handler.codec.mqtt.MqttConnectReturnCode.CONNECTION_REFUSED_NOT_AUTHORIZED;
@ -156,11 +154,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
if (topicName.equals(MqttTopics.DEVICE_PROVISION_REQUEST_TOPIC)) {
try {
TransportProtos.ProvisionDeviceRequestMsg provisionRequestMsg = deviceSessionCtx.getContext().getJsonMqttAdaptor().convertToProvisionRequestMsg(deviceSessionCtx, mqttMsg);
validateProvisionMessage(provisionRequestMsg);
transportService.process(provisionRequestMsg, new DeviceProvisionCallback(ctx, msgId, provisionRequestMsg));
log.trace("[{}][{}] Processing provision publish msg [{}][{}]!", sessionId, deviceSessionCtx.getDeviceId(), topicName, msgId);
} catch (Exception e) {
if (e instanceof JsonParseException || (e.getCause() != null && e.getCause() instanceof JsonParseException)) {
TransportProtos.ProvisionDeviceRequestMsg provisionRequestMsg = deviceSessionCtx.getContext().getProtoMqttAdaptor().convertToProvisionRequestMsg(deviceSessionCtx, mqttMsg);
validateProvisionMessage(provisionRequestMsg);
transportService.process(provisionRequestMsg, new DeviceProvisionCallback(ctx, msgId, provisionRequestMsg));
deviceSessionCtx.setProvisionPayloadType(TransportPayloadType.PROTOBUF);
log.trace("[{}][{}] Processing provision publish msg [{}][{}]!", sessionId, deviceSessionCtx.getDeviceId(), topicName, msgId);
@ -187,6 +187,13 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
}
}
private void validateProvisionMessage(TransportProtos.ProvisionDeviceRequestMsg provisionRequestMsg) {
if (provisionRequestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceKey() != null &&
provisionRequestMsg.getProvisionDeviceCredentialsMsg().getProvisionDeviceSecret() != null &&
provisionRequestMsg.getDeviceName() != null)
throw new RuntimeException("Wrong credentials!");
}
private void processRegularSessionMsg(ChannelHandlerContext ctx, MqttMessage msg) {
switch (msg.fixedHeader().messageType()) {
case PUBLISH:
@ -335,9 +342,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
} else {
deviceSessionCtx.getContext().getProtoMqttAdaptor().convertToPublish(deviceSessionCtx, provisionResponseMsg).ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
}
//TODO: close session with some delay.
//transportService.getScheduler().submit task with 60 seconds delay to close the session.
transportService.getSchedulerExecutor().schedule(() -> processDisconnect(ctx), 60, TimeUnit.SECONDS);
} catch (Exception e) {
log.trace("[{}] Failed to convert device attributes response to MQTT msg", sessionId, e);
}
@ -379,7 +384,6 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
case MqttTopics.GATEWAY_ATTRIBUTES_TOPIC:
case MqttTopics.GATEWAY_RPC_TOPIC:
case MqttTopics.GATEWAY_ATTRIBUTES_RESPONSE_TOPIC:
case MqttTopics.GATEWAY_PROVISION_RESPONSE_TOPIC:
case MqttTopics.DEVICE_PROVISION_RESPONSE_TOPIC:
registerSubQoS(topic, grantedQoSList, reqQoS);
break;
@ -447,7 +451,8 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
private void processConnect(ChannelHandlerContext ctx, MqttConnectMessage msg) {
log.info("[{}] Processing connect msg for client: {}!", sessionId, msg.payload().clientIdentifier());
String userName = msg.payload().userName();
if (DataConstants.PROVISION.equals(userName)) {
String clientId = msg.payload().clientIdentifier();
if (DataConstants.PROVISION.equals(userName) || DataConstants.PROVISION.equals(clientId)) {
deviceSessionCtx.setProvisionOnly(true);
ctx.writeAndFlush(createMqttConnAckMsg(CONNECTION_ACCEPTED));
} else {

View File

@ -153,13 +153,6 @@ public class JsonMqttAdaptor implements MqttTransportAdaptor {
return Optional.of(createMqttPublishMsg(ctx, MqttTopics.DEVICE_PROVISION_RESPONSE_TOPIC, JsonConverter.toJson(provisionResponse)));
}
@Override
public Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, TransportProtos.ProvisionDeviceResponseMsg responseMsg) {
return Optional.of(createMqttPublishMsg(ctx,
MqttTopics.GATEWAY_PROVISION_RESPONSE_TOPIC,
JsonConverter.toGatewayJson(deviceName, responseMsg)));
}
public static JsonElement validateJsonPayload(UUID sessionId, ByteBuf payloadData) throws AdaptorException {
String payload = validatePayload(sessionId, payloadData, false);
try {

View File

@ -69,6 +69,4 @@ public interface MqttTransportAdaptor {
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException;
Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException;
}

View File

@ -187,15 +187,6 @@ public class ProtoMqttAdaptor implements MqttTransportAdaptor {
return Optional.of(createMqttPublishMsg(ctx, MqttTopics.GATEWAY_RPC_TOPIC, payloadBytes));
}
@Override
public Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, TransportProtos.ProvisionDeviceResponseMsg responseMsg) throws AdaptorException {
TransportApiProtos.GatewayProvisionResponseMsg.Builder builder = TransportApiProtos.GatewayProvisionResponseMsg.newBuilder();
builder.setDeviceName(deviceName);
builder.setProvisionDeviceResponseMsg(responseMsg);
byte[] payloadBytes = builder.build().toByteArray();
return Optional.of(createMqttPublishMsg(ctx, MqttTopics.GATEWAY_PROVISION_RESPONSE_TOPIC, payloadBytes));
}
public static byte[] toBytes(ByteBuf inbound) {
byte[] bytes = new byte[inbound.readableBytes()];
int readerIndex = inbound.readerIndex();

View File

@ -40,6 +40,8 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
import java.util.concurrent.ScheduledExecutorService;
/**
* Created by ashvayka on 04.10.18.
*/
@ -88,6 +90,8 @@ public interface TransportService {
void process(SessionInfoProto sessionInfo, ClaimDeviceMsg msg, TransportServiceCallback<Void> callback);
ScheduledExecutorService getSchedulerExecutor();
void registerAsyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener);
void registerSyncSession(SessionInfoProto sessionInfo, SessionMsgListener listener, long timeout);

View File

@ -37,6 +37,8 @@ import org.thingsboard.server.common.data.kv.StringDataEntry;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ClaimDeviceMsg;
import org.thingsboard.server.gen.transport.TransportProtos.CredentialsDataProto.Builder;
import org.thingsboard.server.gen.transport.TransportProtos.CredentialsType;
import org.thingsboard.server.gen.transport.TransportProtos.GetAttributeResponseMsg;
import org.thingsboard.server.gen.transport.TransportProtos.KeyValueProto;
import org.thingsboard.server.gen.transport.TransportProtos.KeyValueType;
@ -46,7 +48,11 @@ import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRespo
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionResponseStatus;
import org.thingsboard.server.gen.transport.TransportProtos.TsKvListProto;
import org.thingsboard.server.gen.transport.TransportProtos.TsKvProto;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCredRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
import javax.xml.crypto.Data;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -554,7 +560,17 @@ public class JsonConverter {
private static TransportProtos.ProvisionDeviceRequestMsg buildProvisionRequestMsg(JsonObject jo) {
return TransportProtos.ProvisionDeviceRequestMsg.newBuilder()
.setDeviceName(getStrValue(jo, DataConstants.DEVICE_NAME, true))
.setX509CertPubKey(getStrValue(jo, DataConstants.CERT_PUB_KEY, false))
.setCredentialsType(TransportProtos.CredentialsType.valueOf(getStrValue(jo, DataConstants.CREDENTIALS_TYPE, false)))
.setCredentialsDataProto(TransportProtos.CredentialsDataProto.newBuilder()
.setValidateDeviceTokenRequestMsg(ValidateDeviceTokenRequestMsg.newBuilder().setToken(getStrValue(jo, DataConstants.TOKEN, false)).build())
.setValidateBasicMqttCredRequestMsg(ValidateBasicMqttCredRequestMsg.newBuilder()
.setClientId(getStrValue(jo, DataConstants.CLIENT_ID, false))
.setUserName(getStrValue(jo, DataConstants.USERNAME, false))
.setPassword(getStrValue(jo, DataConstants.PASSWORD, false))
.build())
.setValidateDeviceX509CertRequestMsg(ValidateDeviceX509CertRequestMsg.newBuilder()
.setHash(getStrValue(jo, DataConstants.PASSWORD, false)).build())
.build())
.setProvisionDeviceCredentialsMsg(buildProvisionDeviceCredentialsMsg(
getStrValue(jo, DataConstants.PROVISION_KEY, true),
getStrValue(jo, DataConstants.PROVISION_SECRET, true)))
@ -567,6 +583,8 @@ public class JsonConverter {
.setProvisionDeviceSecret(provisionSecret)
.build();
}
private static String getStrValue(JsonObject jo, String field, boolean requiredField) {
if (jo.has(field)) {
return jo.get(field).getAsString();

View File

@ -34,7 +34,6 @@ import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.queue.ServiceQueue;
import org.thingsboard.server.common.msg.queue.ServiceType;
@ -49,7 +48,6 @@ import org.thingsboard.server.common.transport.TransportServiceCallback;
import org.thingsboard.server.common.transport.auth.GetOrCreateDeviceFromGatewayResponse;
import org.thingsboard.server.common.transport.auth.TransportDeviceInfo;
import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse;
import org.thingsboard.server.common.transport.util.DataDecodingEncodingService;
import org.thingsboard.server.common.transport.util.JsonUtils;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.gen.transport.TransportProtos.ProvisionDeviceRequestMsg;
@ -77,11 +75,9 @@ import org.thingsboard.server.common.stats.StatsType;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@ -93,7 +89,6 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
/**
* Created by ashvayka on 17.10.18.
@ -236,6 +231,11 @@ public class DefaultTransportService implements TransportService {
}
}
@Override
public ScheduledExecutorService getSchedulerExecutor(){
return this.schedulerExecutor;
}
@Override
public void registerAsyncSession(TransportProtos.SessionInfoProto sessionInfo, SessionMsgListener listener) {
sessions.putIfAbsent(toSessionId(sessionInfo), new SessionMetaData(sessionInfo, TransportProtos.SessionType.ASYNC, listener));