Added routing key and secret
This commit is contained in:
parent
4327f4d3a6
commit
d3bda85a93
@ -88,6 +88,10 @@
|
||||
<groupId>org.thingsboard.common</groupId>
|
||||
<artifactId>queue</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thingsboard.common</groupId>
|
||||
<artifactId>edge-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thingsboard</groupId>
|
||||
<artifactId>dao</artifactId>
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright © 2016-2019 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.service.edge.rpc;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import io.grpc.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.edge.gen.EdgeProtos;
|
||||
import org.thingsboard.server.common.edge.gen.EdgeRpcServiceGrpc;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
@ConditionalOnProperty(prefix = "edges.rpc", value = "enabled", havingValue = "true")
|
||||
public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase {
|
||||
|
||||
@Value("${edges.rpc.port}")
|
||||
private int rpcPort;
|
||||
@Value("${edges.rpc.ssl.enabled}")
|
||||
private boolean sslEnabled;
|
||||
@Value("${edges.rpc.ssl.cert}")
|
||||
private String certFileResource;
|
||||
@Value("${edges.rpc.ssl.privateKey}")
|
||||
private String privateKeyResource;
|
||||
|
||||
private Server server;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
log.info("Initializing Edge RPC service!");
|
||||
ServerBuilder builder = ServerBuilder.forPort(rpcPort).addService(this);
|
||||
if (sslEnabled) {
|
||||
try {
|
||||
File certFile = new File(Resources.getResource(certFileResource).toURI());
|
||||
File privateKeyFile = new File(Resources.getResource(privateKeyResource).toURI());
|
||||
builder.useTransportSecurity(certFile, privateKeyFile);
|
||||
} catch (Exception e) {
|
||||
log.error("Unable to set up SSL context. Reason: " + e.getMessage(), e);
|
||||
throw new RuntimeException("Unable to set up SSL context!", e);
|
||||
}
|
||||
}
|
||||
server = builder.build();
|
||||
log.info("Going to start Edge RPC server using port: {}", rpcPort);
|
||||
try {
|
||||
server.start();
|
||||
} catch (IOException e) {
|
||||
log.error("Failed to start Edge RPC server!", e);
|
||||
throw new RuntimeException("Failed to start Edge RPC server!");
|
||||
}
|
||||
log.info("Edge RPC service initialized!");
|
||||
}
|
||||
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
if (server != null) {
|
||||
server.shutdownNow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamObserver<EdgeProtos.UplinkMsg> sendUplink(StreamObserver<EdgeProtos.DownlinkMsg> responseObserver) {
|
||||
log.info("sendUplink [{}]", responseObserver);
|
||||
return new StreamObserver<EdgeProtos.UplinkMsg>() {
|
||||
|
||||
@Override
|
||||
public void onNext(EdgeProtos.UplinkMsg uplinkMsg) {
|
||||
log.info("onNext [{}]", uplinkMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
log.info("onError", throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
log.info("onCompleted");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -495,6 +495,17 @@ transport:
|
||||
bind_port: "${COAP_BIND_PORT:5683}"
|
||||
timeout: "${COAP_TIMEOUT:10000}"
|
||||
|
||||
# Edges parameters
|
||||
edges:
|
||||
rpc:
|
||||
enabled: "${EDGES_RPC_ENABLED:true}"
|
||||
port: "${EDGES_RPC_PORT:60061}"
|
||||
ssl:
|
||||
# Enable/disable SSL support
|
||||
enabled: "${EDGES_RPC_SSL_ENABLED:false}"
|
||||
cert: "${EDGES_RPC_SSL_CERT:certChainFile.pem}"
|
||||
privateKey: "${EDGES_RPC_SSL_PRIVATE_KEY:privateKeyFile.pem}"
|
||||
|
||||
swagger:
|
||||
api_path_regex: "${SWAGGER_API_PATH_REGEX:/api.*}"
|
||||
security_path_regex: "${SWAGGER_SECURITY_PATH_REGEX:/api.*}"
|
||||
|
||||
@ -26,6 +26,7 @@ import org.thingsboard.server.common.data.page.TextPageData;
|
||||
import org.thingsboard.server.common.data.page.TextPageLink;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface EdgeService {
|
||||
|
||||
@ -35,6 +36,8 @@ public interface EdgeService {
|
||||
|
||||
Edge findEdgeByTenantIdAndName(TenantId tenantId, String name);
|
||||
|
||||
Optional<Edge> findEdgeByRoutingKey(TenantId tenantId, String routingKey);
|
||||
|
||||
Edge saveEdge(Edge edge);
|
||||
|
||||
Edge assignEdgeToCustomer(TenantId tenantId, EdgeId edgeId, CustomerId customerId);
|
||||
|
||||
@ -44,6 +44,8 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
|
||||
private String name;
|
||||
private String type;
|
||||
private String label;
|
||||
private String routingKey;
|
||||
private String secret;
|
||||
private transient JsonNode configuration;
|
||||
|
||||
public Edge() {
|
||||
@ -60,6 +62,8 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
|
||||
this.customerId = edge.getCustomerId();
|
||||
this.type = edge.getType();
|
||||
this.name = edge.getName();
|
||||
this.routingKey = edge.getRoutingKey();
|
||||
this.secret = edge.getSecret();
|
||||
this.configuration = edge.getConfiguration();
|
||||
}
|
||||
|
||||
|
||||
129
common/edge-api/pom.xml
Normal file
129
common/edge-api/pom.xml
Normal file
@ -0,0 +1,129 @@
|
||||
<!--
|
||||
|
||||
Copyright © 2016-2019 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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.thingsboard</groupId>
|
||||
<version>2.4.1-SNAPSHOT</version>
|
||||
<artifactId>common</artifactId>
|
||||
</parent>
|
||||
<groupId>org.thingsboard.common</groupId>
|
||||
<artifactId>edge-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>Thingsboard Server Remote Edge wrapper</name>
|
||||
<url>https://thingsboard.io</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<main.dir>${basedir}/../..</main.dir>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.thingsboard.common</groupId>
|
||||
<artifactId>data</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thingsboard.common</groupId>
|
||||
<artifactId>message</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-netty</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<artifactId>netty-common</artifactId>
|
||||
<groupId>io.netty</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-protobuf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.grpc</groupId>
|
||||
<artifactId>grpc-stub</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.xolstice.maven.plugins</groupId>
|
||||
<artifactId>protobuf-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>thingsboard-repo-deploy</id>
|
||||
<name>ThingsBoard Repo Deployment</name>
|
||||
<url>https://repo.thingsboard.io/artifactory/libs-release-public</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
</project>
|
||||
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Copyright © 2016-2019 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.edge.rpc;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import io.grpc.ManagedChannel;
|
||||
import io.grpc.netty.GrpcSslContexts;
|
||||
import io.grpc.netty.NettyChannelBuilder;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.thingsboard.server.common.edge.gen.EdgeProtos;
|
||||
import org.thingsboard.server.common.edge.gen.EdgeRpcServiceGrpc;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class EdgeGrpcClient implements EdgeRpcClient {
|
||||
|
||||
@Value("${cloud.rpc.host}")
|
||||
private String rpcHost;
|
||||
@Value("${cloud.rpc.port}")
|
||||
private int rpcPort;
|
||||
@Value("${cloud.rpc.timeout}")
|
||||
private int timeoutSecs;
|
||||
@Value("${cloud.rpc.ssl.enabled}")
|
||||
private boolean sslEnabled;
|
||||
@Value("${cloud.rpc.ssl.cert}")
|
||||
private String certResource;
|
||||
|
||||
private ManagedChannel channel;
|
||||
|
||||
private StreamObserver<EdgeProtos.UplinkMsg> inputStream;
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
NettyChannelBuilder builder = NettyChannelBuilder.forAddress(rpcHost, rpcPort).usePlaintext();
|
||||
if (sslEnabled) {
|
||||
try {
|
||||
builder.sslContext(GrpcSslContexts.forClient().trustManager(new File(Resources.getResource(certResource).toURI())).build());
|
||||
} catch (URISyntaxException | SSLException e) {
|
||||
log.error("Failed to initialize channel!", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
channel = builder.build();
|
||||
EdgeRpcServiceGrpc.EdgeRpcServiceStub stub = EdgeRpcServiceGrpc.newStub(channel);
|
||||
StreamObserver<EdgeProtos.DownlinkMsg> responseObserver = new StreamObserver<EdgeProtos.DownlinkMsg>() {
|
||||
@Override
|
||||
public void onNext(EdgeProtos.DownlinkMsg downlinkMsg) {
|
||||
log.info("onNext [{}]", downlinkMsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable throwable) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
|
||||
}
|
||||
};
|
||||
inputStream = stub.sendUplink(responseObserver);
|
||||
inputStream.onNext(EdgeProtos.UplinkMsg.newBuilder().setMsgType(EdgeProtos.UplinkMsgType.DELETE_DEVICE_MESSAGE).build());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright © 2016-2019 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.edge.rpc;
|
||||
|
||||
public interface EdgeRpcClient {
|
||||
|
||||
void connect();
|
||||
}
|
||||
49
common/edge-api/src/main/proto/edge.proto
Normal file
49
common/edge-api/src/main/proto/edge.proto
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright © 2016-2019 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.
|
||||
*/
|
||||
syntax = "proto3";
|
||||
|
||||
option java_package = "org.thingsboard.server.common.edge.gen";
|
||||
option java_outer_classname = "EdgeProtos";
|
||||
|
||||
package edge;
|
||||
|
||||
// Interface exported by the ThingsBoard PRC Edge.
|
||||
service EdgeRpcService {
|
||||
|
||||
rpc sendUplink(stream UplinkMsg) returns (stream DownlinkMsg) {}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Data Structures;
|
||||
*/
|
||||
message UplinkMsg {
|
||||
UplinkMsgType msgType = 1;
|
||||
}
|
||||
|
||||
message DownlinkMsg {
|
||||
DownlinkMsgType msgType = 1;
|
||||
}
|
||||
|
||||
enum UplinkMsgType {
|
||||
SAVE_DEVICE_MESSAGE = 0;
|
||||
DELETE_DEVICE_MESSAGE = 1;
|
||||
}
|
||||
|
||||
enum DownlinkMsgType {
|
||||
SAVE_ENTITY_MESSAGE = 0;
|
||||
DELETE_ENTITY_MESSAGE = 1;
|
||||
}
|
||||
@ -40,6 +40,7 @@
|
||||
<module>queue</module>
|
||||
<module>transport</module>
|
||||
<module>dao-api</module>
|
||||
<module>edge-api</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
@ -46,6 +46,7 @@ import org.thingsboard.server.dao.entity.AbstractEntityService;
|
||||
import org.thingsboard.server.dao.exception.DataValidationException;
|
||||
import org.thingsboard.server.dao.service.DataValidator;
|
||||
import org.thingsboard.server.dao.service.PaginatedRemover;
|
||||
import org.thingsboard.server.dao.service.Validator;
|
||||
import org.thingsboard.server.dao.tenant.TenantDao;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@ -111,6 +112,13 @@ public class BaseEdgeService extends AbstractEntityService implements EdgeServic
|
||||
return edgeOpt.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Edge> findEdgeByRoutingKey(TenantId tenantId, String routingKey) {
|
||||
log.trace("Executing findEdgeByRoutingKey [{}]", routingKey);
|
||||
Validator.validateString(routingKey, "Incorrect edge routingKey for search request.");
|
||||
return edgeDao.findByRoutingKey(tenantId.getId(), routingKey);
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = EDGE_CACHE, key = "{#edge.tenantId, #edge.name}")
|
||||
@Override
|
||||
public Edge saveEdge(Edge edge) {
|
||||
|
||||
@ -86,4 +86,9 @@ public class CassandraEdgeDao extends CassandraAbstractSearchTextDao<EdgeEntity,
|
||||
public ListenableFuture<List<EntitySubtype>> findTenantEdgeTypesAsync(UUID tenantId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Edge> findByRoutingKey(UUID tenantId, String routingKey) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,5 +116,12 @@ public interface EdgeDao extends Dao<Edge> {
|
||||
*/
|
||||
ListenableFuture<List<EntitySubtype>> findTenantEdgeTypesAsync(UUID tenantId);
|
||||
|
||||
/**
|
||||
* Find edge by routing Key.
|
||||
*
|
||||
* @param routingKey the edge routingKey
|
||||
* @return the optional edge object
|
||||
*/
|
||||
Optional<Edge> findByRoutingKey(UUID tenantId, String routingKey);
|
||||
|
||||
}
|
||||
|
||||
@ -361,7 +361,8 @@ public class ModelConstants {
|
||||
public static final String EDGE_CONFIGURATION_PROPERTY = "configuration";
|
||||
public static final String EDGE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
|
||||
|
||||
public static final String EDGE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "edge_by_tenant_and_search_text";
|
||||
public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key";
|
||||
public static final String EDGE_SECRET_PROPERTY = "secret";
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@ -37,6 +37,8 @@ import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CONFIGURATION
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LABEL_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_SECRET_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TYPE_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
|
||||
@ -70,6 +72,12 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
|
||||
@Column(name = SEARCH_TEXT_PROPERTY)
|
||||
private String searchText;
|
||||
|
||||
@Column(name = EDGE_ROUTING_KEY_PROPERTY)
|
||||
private String routingKey;
|
||||
|
||||
@Column(name = EDGE_SECRET_PROPERTY)
|
||||
private String secret;
|
||||
|
||||
@Column(name = EDGE_CONFIGURATION_PROPERTY, codec = JsonCodec.class)
|
||||
private JsonNode configuration;
|
||||
|
||||
@ -90,6 +98,8 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
|
||||
this.type = edge.getType();
|
||||
this.name = edge.getName();
|
||||
this.label = edge.getLabel();
|
||||
this.routingKey = edge.getRoutingKey();
|
||||
this.secret = edge.getSecret();
|
||||
this.configuration = edge.getConfiguration();
|
||||
this.additionalInfo = edge.getAdditionalInfo();
|
||||
}
|
||||
@ -112,6 +122,8 @@ public class EdgeEntity implements SearchTextEntity<Edge> {
|
||||
edge.setType(type);
|
||||
edge.setName(name);
|
||||
edge.setLabel(label);
|
||||
edge.setRoutingKey(routingKey);
|
||||
edge.setSecret(secret);
|
||||
edge.setConfiguration(configuration);
|
||||
edge.setAdditionalInfo(additionalInfo);
|
||||
return edge;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@ -35,11 +35,12 @@ import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.ASSET_CUSTOMER_ID_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_COLUMN_FAMILY_NAME;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CUSTOMER_ID_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_LABEL_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_SECRET_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TENANT_ID_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_TYPE_PROPERTY;
|
||||
import static org.thingsboard.server.dao.model.ModelConstants.SEARCH_TEXT_PROPERTY;
|
||||
@ -69,6 +70,12 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
|
||||
@Column(name = SEARCH_TEXT_PROPERTY)
|
||||
private String searchText;
|
||||
|
||||
@Column(name = EDGE_ROUTING_KEY_PROPERTY)
|
||||
private String routingKey;
|
||||
|
||||
@Column(name = EDGE_SECRET_PROPERTY)
|
||||
private String secret;
|
||||
|
||||
@Type(type = "json")
|
||||
@Column(name = ModelConstants.EDGE_CONFIGURATION_PROPERTY)
|
||||
private JsonNode configuration;
|
||||
@ -94,6 +101,8 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
|
||||
this.type = edge.getType();
|
||||
this.name = edge.getName();
|
||||
this.label = edge.getLabel();
|
||||
this.routingKey = edge.getRoutingKey();
|
||||
this.secret = edge.getSecret();
|
||||
this.configuration = edge.getConfiguration();
|
||||
this.additionalInfo = edge.getAdditionalInfo();
|
||||
}
|
||||
@ -125,6 +134,8 @@ public class EdgeEntity extends BaseSqlEntity<Edge> implements SearchTextEntity<
|
||||
edge.setType(type);
|
||||
edge.setName(name);
|
||||
edge.setLabel(label);
|
||||
edge.setRoutingKey(routingKey);
|
||||
edge.setSecret(secret);
|
||||
edge.setConfiguration(configuration);
|
||||
edge.setAdditionalInfo(additionalInfo);
|
||||
return edge;
|
||||
|
||||
@ -76,4 +76,5 @@ public interface EdgeRepository extends CrudRepository<EdgeEntity, String> {
|
||||
|
||||
List<EdgeEntity> findEdgesByTenantIdAndIdIn(String tenantId, List<String> edgeIds);
|
||||
|
||||
EdgeEntity findByRoutingKey(String routingKey);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* 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,
|
||||
@ -126,6 +126,12 @@ public class JpaEdgeDao extends JpaAbstractSearchTextDao<EdgeEntity, Edge> imple
|
||||
return service.submit(() -> convertTenantEdgeTypesToDto(tenantId, edgeRepository.findTenantEdgeTypes(fromTimeUUID(tenantId))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Edge> findByRoutingKey(UUID tenantId, String routingKey) {
|
||||
Edge edge = DaoUtil.getData(edgeRepository.findByRoutingKey(routingKey));
|
||||
return Optional.ofNullable(edge);
|
||||
}
|
||||
|
||||
private List<EntitySubtype> convertTenantEdgeTypesToDto(UUID tenantId, List<String> types) {
|
||||
List<EntitySubtype> list = Collections.emptyList();
|
||||
if (types != null && !types.isEmpty()) {
|
||||
|
||||
@ -257,6 +257,8 @@ CREATE TABLE IF NOT EXISTS edge (
|
||||
type varchar(255),
|
||||
name varchar(255),
|
||||
label varchar(255),
|
||||
routing_key varchar(255),
|
||||
secret varchar(255),
|
||||
search_text varchar(255),
|
||||
tenant_id varchar(31)
|
||||
);
|
||||
5
pom.xml
5
pom.xml
@ -406,6 +406,11 @@
|
||||
<artifactId>coap</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thingsboard.common</groupId>
|
||||
<artifactId>edge-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thingsboard</groupId>
|
||||
<artifactId>dao</artifactId>
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
<div layout="row">
|
||||
<md-button ngclipboard data-clipboard-action="copy"
|
||||
ngclipboard-success="onEdgeIdCopied(e)"
|
||||
ngclipboard-success="onEdgeIdCopied()"
|
||||
data-clipboard-text="{{edge.id.id}}" ng-show="!isEdit"
|
||||
class="md-raised">
|
||||
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
|
||||
@ -69,4 +69,34 @@
|
||||
<textarea ng-model="edge.additionalInfo.description" rows="2"></textarea>
|
||||
</md-input-container>
|
||||
</fieldset>
|
||||
<div layout="row">
|
||||
<md-input-container class="md-block" flex>
|
||||
<label translate>edge.edge-key</label>
|
||||
<input ng-model="edge.routingKey" disabled>
|
||||
</md-input-container>
|
||||
<md-button class="md-icon-button" style="margin-top: 14px;"
|
||||
ngclipboard data-clipboard-action="copy"
|
||||
ngclipboard-success="onEdgeInfoCopied('key')"
|
||||
data-clipboard-text="{{edge.routingKey}}">
|
||||
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
|
||||
<md-tooltip md-direction="top">
|
||||
{{ 'edge.copy-edge-key' | translate }}
|
||||
</md-tooltip>
|
||||
</md-button>
|
||||
</div>
|
||||
<div layout="row">
|
||||
<md-input-container class="md-block" flex>
|
||||
<label translate>edge.edge-secret</label>
|
||||
<input ng-model="edge.secret" disabled>
|
||||
</md-input-container>
|
||||
<md-button class="md-icon-button" style="margin-top: 14px;"
|
||||
ngclipboard data-clipboard-action="copy"
|
||||
data-clipboard-text="{{edge.secret}}"
|
||||
ngclipboard-success="onEdgeInfoCopied('secret')">
|
||||
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon>
|
||||
<md-tooltip md-direction="top">
|
||||
{{ 'edge.copy-edge-secret' | translate }}
|
||||
</md-tooltip>
|
||||
</md-button>
|
||||
</div>
|
||||
</md-content>
|
||||
|
||||
@ -20,7 +20,7 @@ import edgeFieldsetTemplate from './edge-fieldset.tpl.html';
|
||||
/* eslint-enable import/no-unresolved, import/default */
|
||||
|
||||
/*@ngInject*/
|
||||
export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, toast, types, customerService) {
|
||||
export default function EdgeDirective($compile, $templateCache, $translate, $mdDialog, $document, utils, toast, types, customerService) {
|
||||
var linker = function (scope, element) {
|
||||
var template = $templateCache.get(edgeFieldsetTemplate);
|
||||
element.html(template);
|
||||
@ -32,6 +32,10 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD
|
||||
|
||||
scope.$watch('edge', function(newVal) {
|
||||
if (newVal) {
|
||||
if (!scope.edge.id) {
|
||||
scope.edge.routingKey = utils.guid('');
|
||||
scope.edge.secret = generateSecret(20);
|
||||
}
|
||||
if (scope.edge.customerId && scope.edge.customerId.id !== types.id.nullUid) {
|
||||
scope.isAssignedToCustomer = true;
|
||||
customerService.getShortCustomerInfo(scope.edge.customerId.id).then(
|
||||
@ -48,12 +52,38 @@ export default function EdgeDirective($compile, $templateCache, $translate, $mdD
|
||||
}
|
||||
});
|
||||
|
||||
function generateSecret(length) {
|
||||
if (angular.isUndefined(length) || length == null) {
|
||||
length = 1;
|
||||
}
|
||||
var l = length > 10 ? 10 : length;
|
||||
var str = Math.random().toString(36).substr(2, l);
|
||||
if(str.length >= length){
|
||||
return str;
|
||||
}
|
||||
return str.concat(generateSecret(length - str.length));
|
||||
}
|
||||
|
||||
scope.onEdgeIdCopied = function() {
|
||||
toast.showSuccess($translate.instant('edge.id-copied-message'), 750, angular.element(element).parent().parent(), 'bottom left');
|
||||
};
|
||||
|
||||
$compile(element.contents())(scope);
|
||||
|
||||
scope.onEdgeInfoCopied = function(type) {
|
||||
let translateInstant = "";
|
||||
switch (type) {
|
||||
case 'key':
|
||||
translateInstant = "edge.edge-key-copied-message";
|
||||
break;
|
||||
case 'secret':
|
||||
translateInstant = "edge.edge-secret-copied-message";
|
||||
break;
|
||||
}
|
||||
toast.showSuccess($translate.instant(translateInstant), 750, angular.element(element).parent().parent(), 'top left');
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
return {
|
||||
restrict: "E",
|
||||
|
||||
@ -602,6 +602,16 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
case types.entityType.edge:
|
||||
openImportDialogCSV($event, entityType, 'edge.import', 'edge.edge-file').then(
|
||||
function success() {
|
||||
deferred.resolve();
|
||||
},
|
||||
function fail() {
|
||||
deferred.reject();
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -777,7 +777,13 @@
|
||||
"unassign-from-edge": "Unassign from edge",
|
||||
"dashboards": "Edge Dashboards",
|
||||
"manage-edge-rulechains": "Manage edge rule chains",
|
||||
"rulechains": "Edge Rule Chains"
|
||||
"rulechains": "Edge Rule Chains",
|
||||
"edge-key": "Edge key",
|
||||
"copy-edge-key": "Copy edge key",
|
||||
"edge-key-copied-message": "Edge key has been copied to clipboard",
|
||||
"edge-secret": "Edge secret",
|
||||
"copy-edge-secret": "Copy edge secret",
|
||||
"edge-secret-copied-message": "Edge secret has been copied to clipboard"
|
||||
},
|
||||
"error": {
|
||||
"unable-to-connect": "Unable to connect to the server! Please check your internet connection.",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user