Browse Source

Merge pull request #6035 from volodymyr-babak/edge-ce-refactoring

[3.3.4] Edge Community Edition support
pull/6126/head
Andrew Shvayka 5 years ago
committed by GitHub
parent
commit
282a6bc990
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  2. 70
      application/src/main/java/org/thingsboard/server/controller/EdgeController.java
  3. 4
      application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
  4. 1
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  5. 110
      application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeLicenseService.java
  6. 6
      application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java
  7. 26
      application/src/main/java/org/thingsboard/server/service/edge/EdgeLicenseService.java
  8. 2
      application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
  9. 8
      application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java
  10. 2
      application/src/main/java/org/thingsboard/server/service/importing/BulkImportColumnType.java
  11. 16
      application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
  12. 2
      application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
  13. 2
      application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java
  14. 378
      application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java
  15. 20
      common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java
  16. 4
      common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java
  17. 6
      common/edge-api/src/main/proto/edge.proto
  18. 6
      dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java
  19. 2
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  20. 14
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEdgeEntity.java
  21. 2
      dao/src/main/resources/sql/schema-entities.sql
  22. 2
      dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
  23. 4
      dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java
  24. 2
      dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java
  25. 10
      ui-ngx/src/app/core/http/entity.service.ts
  26. 4
      ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts
  27. 12
      ui-ngx/src/app/modules/home/components/import-export/table-columns-assignment.component.ts
  28. 26
      ui-ngx/src/app/modules/home/pages/edge/edge.component.html
  29. 7
      ui-ngx/src/app/modules/home/pages/edge/edge.component.ts
  30. 2
      ui-ngx/src/app/shared/models/edge.models.ts
  31. 2
      ui-ngx/src/app/shared/models/entity.models.ts
  32. 8
      ui-ngx/src/assets/locale/locale.constant-cs_CZ.json
  33. 6
      ui-ngx/src/assets/locale/locale.constant-de_DE.json
  34. 10
      ui-ngx/src/assets/locale/locale.constant-en_US.json
  35. 6
      ui-ngx/src/assets/locale/locale.constant-es_ES.json
  36. 6
      ui-ngx/src/assets/locale/locale.constant-fr_FR.json
  37. 8
      ui-ngx/src/assets/locale/locale.constant-tr_TR.json

4
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -123,7 +123,6 @@ import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.action.EntityActionService;
import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.edge.EdgeLicenseService;
import org.thingsboard.server.service.edge.EdgeNotificationService;
import org.thingsboard.server.service.edge.rpc.EdgeRpcService;
import org.thingsboard.server.service.ota.OtaPackageStateService;
@ -269,9 +268,6 @@ public abstract class BaseController {
@Autowired(required = false)
protected EdgeRpcService edgeGrpcService;
@Autowired(required = false)
protected EdgeLicenseService edgeLicenseService;
@Autowired
protected EntityActionService entityActionService;

70
application/src/main/java/org/thingsboard/server/controller/EdgeController.java

@ -15,7 +15,6 @@
*/
package org.thingsboard.server.controller;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.ListenableFuture;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@ -23,7 +22,6 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@ -52,7 +50,6 @@ import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants;
@ -118,11 +115,7 @@ public class EdgeController extends BaseController {
checkParameter(EDGE_ID, strEdgeId);
try {
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
Edge edge = checkEdgeId(edgeId, Operation.READ);
if (Authority.CUSTOMER_USER.equals(getCurrentUser().getAuthority())) {
cleanUpLicenseKey(edge);
}
return edge;
return checkEdgeId(edgeId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -139,11 +132,7 @@ public class EdgeController extends BaseController {
checkParameter(EDGE_ID, strEdgeId);
try {
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
EdgeInfo edgeInfo = checkEdgeInfoId(edgeId, Operation.READ);
if (Authority.CUSTOMER_USER.equals(getCurrentUser().getAuthority())) {
cleanUpLicenseKey(edgeInfo);
}
return edgeInfo;
return checkEdgeInfoId(edgeId, Operation.READ);
} catch (Exception e) {
throw handleException(e);
}
@ -525,11 +514,6 @@ public class EdgeController extends BaseController {
} else {
result = edgeService.findEdgesByTenantIdAndCustomerId(tenantId, customerId, pageLink);
}
if (Authority.CUSTOMER_USER.equals(user.getAuthority())) {
for (Edge edge : result.getData()) {
cleanUpLicenseKey(edge);
}
}
return checkNotNull(result);
} catch (Exception e) {
throw handleException(e);
@ -570,11 +554,6 @@ public class EdgeController extends BaseController {
} else {
result = edgeService.findEdgeInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink);
}
if (Authority.CUSTOMER_USER.equals(user.getAuthority())) {
for (Edge edge : result.getData()) {
cleanUpLicenseKey(edge);
}
}
return checkNotNull(result);
} catch (Exception e) {
throw handleException(e);
@ -606,11 +585,6 @@ public class EdgeController extends BaseController {
edgesFuture = edgeService.findEdgesByTenantIdCustomerIdAndIdsAsync(tenantId, customerId, edgeIds);
}
List<Edge> edges = edgesFuture.get();
if (Authority.CUSTOMER_USER.equals(user.getAuthority())) {
for (Edge edge : edges) {
cleanUpLicenseKey(edge);
}
}
return checkNotNull(edges);
} catch (Exception e) {
throw handleException(e);
@ -642,11 +616,6 @@ public class EdgeController extends BaseController {
return false;
}
}).collect(Collectors.toList());
if (Authority.CUSTOMER_USER.equals(user.getAuthority())) {
for (Edge edge : edges) {
cleanUpLicenseKey(edge);
}
}
return edges;
} catch (Exception e) {
throw handleException(e);
@ -732,39 +701,4 @@ public class EdgeController extends BaseController {
}
});
}
private void cleanUpLicenseKey(Edge edge) {
edge.setEdgeLicenseKey(null);
}
@ApiOperation(value = "Check edge license (checkInstance)",
notes = "Checks license request from edge service by forwarding request to license portal.",
produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = "/license/checkInstance", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<JsonNode> checkInstance(@RequestBody JsonNode request) throws ThingsboardException {
log.debug("Checking instance [{}]", request);
try {
return edgeLicenseService.checkInstance(request);
} catch (Exception e) {
log.error("Error occurred: [{}]", e.getMessage(), e);
throw new ThingsboardException(e, ThingsboardErrorCode.SUBSCRIPTION_VIOLATION);
}
}
@ApiOperation(value = "Activate edge instance (activateInstance)",
notes = "Activates edge license on license portal.",
produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = "/license/activateInstance", params = {"licenseSecret", "releaseDate"}, method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<JsonNode> activateInstance(@RequestParam String licenseSecret,
@RequestParam String releaseDate) throws ThingsboardException {
log.debug("Activating instance [{}], [{}]", licenseSecret, releaseDate);
try {
return edgeLicenseService.activateInstance(licenseSecret, releaseDate);
} catch (Exception e) {
log.error("Error occurred: [{}]", e.getMessage(), e);
throw new ThingsboardException(e, ThingsboardErrorCode.SUBSCRIPTION_VIOLATION);
}
}
}

4
application/src/main/java/org/thingsboard/server/controller/RuleChainController.java

@ -683,7 +683,7 @@ public class RuleChainController extends BaseController {
checkParameter(RULE_CHAIN_ID, strRuleChainId);
try {
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
Edge edge = checkEdgeId(edgeId, Operation.READ);
Edge edge = checkEdgeId(edgeId, Operation.WRITE);
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
checkRuleChain(ruleChainId, Operation.READ);
@ -723,7 +723,7 @@ public class RuleChainController extends BaseController {
checkParameter(RULE_CHAIN_ID, strRuleChainId);
try {
EdgeId edgeId = new EdgeId(toUUID(strEdgeId));
Edge edge = checkEdgeId(edgeId, Operation.READ);
Edge edge = checkEdgeId(edgeId, Operation.WRITE);
RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
RuleChain ruleChain = checkRuleChain(ruleChainId, Operation.READ);

1
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -217,6 +217,7 @@ public class ThingsboardInstallService {
case "3.3.3":
log.info("Upgrading ThingsBoard from version 3.3.3 to 3.3.4 ...");
log.info("Updating system data...");
databaseEntitiesUpgradeService.upgradeDatabase("3.3.3");
systemDataLoaderService.updateSystemWidgets();
break;

110
application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeLicenseService.java

@ -1,110 +0,0 @@
/**
* Copyright © 2016-2022 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;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.thingsboard.server.queue.util.TbCoreComponent;
import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.HashMap;
import java.util.Map;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
@Service
@TbCoreComponent
@Slf4j
public class DefaultEdgeLicenseService implements EdgeLicenseService {
private RestTemplate restTemplate;
private static final String EDGE_LICENSE_SERVER_ENDPOINT = "https://license.thingsboard.io";
@Value("${edges.enabled:false}")
private boolean edgesEnabled;
@PostConstruct
public void init() {
if (edgesEnabled) {
initRestTemplate();
}
}
@Override
public ResponseEntity<JsonNode> checkInstance(JsonNode request) {
return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/checkInstance", request, JsonNode.class);
}
@Override
public ResponseEntity<JsonNode> activateInstance(String edgeLicenseSecret, String releaseDate) {
Map<String, String> params = new HashMap<>();
params.put("licenseSecret", edgeLicenseSecret);
params.put("releaseDate", releaseDate);
return this.restTemplate.postForEntity(EDGE_LICENSE_SERVER_ENDPOINT + "/api/license/activateInstance?licenseSecret={licenseSecret}&releaseDate={releaseDate}", null, JsonNode.class, params);
}
private void initRestTemplate() {
boolean jdkHttpClientEnabled = isNotEmpty(System.getProperty("tb.proxy.jdk")) && System.getProperty("tb.proxy.jdk").equalsIgnoreCase("true");
boolean systemProxyEnabled = isNotEmpty(System.getProperty("tb.proxy.system")) && System.getProperty("tb.proxy.system").equalsIgnoreCase("true");
boolean proxyEnabled = isNotEmpty(System.getProperty("tb.proxy.host")) && isNotEmpty(System.getProperty("tb.proxy.port"));
if (jdkHttpClientEnabled) {
log.warn("Going to use plain JDK Http Client!");
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
if (proxyEnabled) {
log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port"));
factory.setProxy(new Proxy(Proxy.Type.HTTP, InetSocketAddress.createUnresolved(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port")))));
}
this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
} else {
CloseableHttpClient httpClient;
HttpComponentsClientHttpRequestFactory requestFactory;
if (systemProxyEnabled) {
log.warn("Going to use System Proxy Server!");
httpClient = HttpClients.createSystem();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
} else if (proxyEnabled) {
log.warn("Going to use Proxy Server: [{}:{}]", System.getProperty("tb.proxy.host"), System.getProperty("tb.proxy.port"));
httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).setProxy(new HttpHost(System.getProperty("tb.proxy.host"), Integer.parseInt(System.getProperty("tb.proxy.port")), "https")).build();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
} else {
httpClient = HttpClients.custom().setSSLHostnameVerifier(new DefaultHostnameVerifier()).build();
requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
this.restTemplate = new RestTemplate(requestFactory);
}
}
}
}

6
application/src/main/java/org/thingsboard/server/service/edge/EdgeBulkImportService.java

@ -55,12 +55,6 @@ public class EdgeBulkImportService extends AbstractBulkImportService<Edge> {
case DESCRIPTION:
additionalInfo.set("description", new TextNode(value));
break;
case EDGE_LICENSE_KEY:
entity.setEdgeLicenseKey(value);
break;
case CLOUD_ENDPOINT:
entity.setCloudEndpoint(value);
break;
case ROUTING_KEY:
entity.setRoutingKey(value);
break;

26
application/src/main/java/org/thingsboard/server/service/edge/EdgeLicenseService.java

@ -1,26 +0,0 @@
/**
* Copyright © 2016-2022 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;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.http.ResponseEntity;
public interface EdgeLicenseService {
ResponseEntity<JsonNode> checkInstance(JsonNode request);
ResponseEntity<JsonNode> activateInstance(String licenseSecret, String releaseDate);
}

2
application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java

@ -690,8 +690,6 @@ public final class EdgeGrpcSession implements Closeable {
.setType(edge.getType())
.setRoutingKey(edge.getRoutingKey())
.setSecret(edge.getSecret())
.setEdgeLicenseKey(edge.getEdgeLicenseKey())
.setCloudEndpoint(edge.getCloudEndpoint())
.setAdditionalInfo(JacksonUtil.toString(edge.getAdditionalInfo()))
.setCloudType("CE");
if (edge.getCustomerId() != null) {

8
application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeSyncCursor.java

@ -41,17 +41,17 @@ public class EdgeSyncCursor {
int currentIdx = 0;
public EdgeSyncCursor(EdgeContextComponent ctx, Edge edge) {
fetchers.add(new SystemWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService()));
fetchers.add(new TenantWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService()));
fetchers.add(new DeviceProfilesEdgeEventFetcher(ctx.getDeviceProfileService()));
fetchers.add(new RuleChainsEdgeEventFetcher(ctx.getRuleChainService()));
fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService(), ctx.getFreemarkerConfig()));
fetchers.add(new DeviceProfilesEdgeEventFetcher(ctx.getDeviceProfileService()));
fetchers.add(new TenantAdminUsersEdgeEventFetcher(ctx.getUserService()));
if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) {
fetchers.add(new CustomerEdgeEventFetcher());
fetchers.add(new CustomerUsersEdgeEventFetcher(ctx.getUserService(), edge.getCustomerId()));
}
fetchers.add(new AdminSettingsEdgeEventFetcher(ctx.getAdminSettingsService(), ctx.getFreemarkerConfig()));
fetchers.add(new AssetsEdgeEventFetcher(ctx.getAssetService()));
fetchers.add(new SystemWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService()));
fetchers.add(new TenantWidgetsBundlesEdgeEventFetcher(ctx.getWidgetsBundleService()));
fetchers.add(new DashboardsEdgeEventFetcher(ctx.getDashboardService()));
}

2
application/src/main/java/org/thingsboard/server/service/importing/BulkImportColumnType.java

@ -45,8 +45,6 @@ public enum BulkImportColumnType {
LWM2M_SERVER_CLIENT_SECRET_KEY("clientSecretKey"),
IS_GATEWAY,
DESCRIPTION,
EDGE_LICENSE_KEY,
CLOUD_ENDPOINT,
ROUTING_KEY,
SECRET;

16
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java

@ -512,6 +512,22 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.error("Failed updating schema!!!", e);
}
break;
case "3.3.3":
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
log.info("Updating schema ...");
try {
conn.createStatement().execute("ALTER TABLE edge DROP COLUMN edge_license_key;"); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
conn.createStatement().execute("ALTER TABLE edge DROP COLUMN cloud_endpoint;"); //NOSONAR, ignoring because method used to execute thingsboard database upgrade script
} catch (Exception ignored) {
}
log.info("Updating schema settings...");
conn.createStatement().execute("UPDATE tb_schema_settings SET schema_version = 3003004;");
log.info("Schema updated.");
} catch (Exception e) {
log.error("Failed updating schema!!!", e);
}
break;
default:
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
}

2
application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java

@ -606,8 +606,6 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
edge.setType(type);
edge.setSecret(RandomStringUtils.randomAlphanumeric(20));
edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20));
edge.setEdgeLicenseKey(RandomStringUtils.randomAlphanumeric(20));
edge.setCloudEndpoint("http://localhost:8080");
return edge;
}
}

2
application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java

@ -105,8 +105,6 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
Assert.assertNotNull(savedEdge.getCustomerId());
Assert.assertEquals(NULL_UUID, savedEdge.getCustomerId().getId());
Assert.assertEquals(edge.getName(), savedEdge.getName());
Assert.assertTrue(StringUtils.isNoneBlank(savedEdge.getEdgeLicenseKey()));
Assert.assertTrue(StringUtils.isNoneBlank(savedEdge.getCloudEndpoint()));
savedEdge.setName("My new edge");
doPost("/api/edge", savedEdge, Edge.class);

378
application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java

@ -25,7 +25,6 @@ import com.google.gson.JsonObject;
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.awaitility.Awaitility;
import org.junit.After;
@ -34,6 +33,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DataConstants;
@ -116,7 +116,6 @@ import org.thingsboard.server.gen.edge.v1.UserUpdateMsg;
import org.thingsboard.server.gen.edge.v1.WidgetTypeUpdateMsg;
import org.thingsboard.server.gen.edge.v1.WidgetsBundleUpdateMsg;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.cluster.TbClusterService;
import java.util.ArrayList;
import java.util.List;
@ -129,7 +128,6 @@ import java.util.concurrent.TimeUnit;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@Slf4j
abstract public class BaseEdgeTest extends AbstractControllerTest {
private static final String CUSTOM_DEVICE_PROFILE_NAME = "Thermostat";
@ -165,7 +163,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
tenantAdmin.setLastName("Downs");
tenantAdmin = createUserAndLogin(tenantAdmin, "testPassword1");
// sleep 1 seconds to avoid CREDENTIALS updated message for the user
// sleep 0.5 second to avoid CREDENTIALS updated message for the user
// user credentials is going to be stored and updated event pushed to edge notification service
// while service will be processing this event edge could be already added and additional message will be pushed
Thread.sleep(500);
@ -176,7 +174,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
edgeImitator.expectMessageAmount(13);
edgeImitator.connect();
testReceivedInitialData();
verifyEdgeConnectionAndInitialData();
}
@After
@ -187,41 +185,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
loginSysAdmin();
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
doDelete("/api/tenant/" + savedTenant.getUuidId())
.andExpect(status().isOk());
}
@Test
public void test() throws Exception {
testDevices();
testAssets();
testRuleChains();
testDashboards();
testRelations();
testAlarms();
testEntityView();
testCustomerAndNewUser();
testWidgetsBundleAndWidgetType();
testTimeseries();
testAttributes();
testRpcCall();
testTimeseriesWithFailures();
testSendMessagesToCloud();
}
private void installation() throws Exception {
edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class);
@ -230,12 +197,12 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
Device savedDevice = saveDevice("Edge Device 1", CUSTOM_DEVICE_PROFILE_NAME);
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/device/" + savedDevice.getId().getId().toString(), Device.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/device/" + savedDevice.getUuidId(), Device.class);
Asset savedAsset = saveAsset("Edge Asset 1");
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/asset/" + savedAsset.getUuidId(), Asset.class);
}
private void extendDeviceProfileData(DeviceProfile deviceProfile) {
@ -267,8 +234,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
profileData.setProvisionConfiguration(new AllowCreateNewDevicesDeviceProfileProvisionConfiguration("123"));
}
private void testReceivedInitialData() throws Exception {
log.info("Checking received data");
private void verifyEdgeConnectionAndInitialData() throws Exception {
Assert.assertTrue(edgeImitator.waitForMessages());
EdgeConfiguration configuration = edgeImitator.getConfiguration();
@ -283,7 +249,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
UUID deviceUUID = new UUID(deviceUpdateMsg.getIdMSB(), deviceUpdateMsg.getIdLSB());
Device device = doGet("/api/device/" + deviceUUID.toString(), Device.class);
Assert.assertNotNull(device);
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?",
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/devices?",
new TypeReference<PageData<Device>>() {}, new PageLink(100)).getData();
Assert.assertTrue(edgeDevices.contains(device));
@ -310,7 +276,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
UUID assetUUID = new UUID(assetUpdateMsg.getIdMSB(), assetUpdateMsg.getIdLSB());
Asset asset = doGet("/api/asset/" + assetUUID.toString(), Asset.class);
Assert.assertNotNull(asset);
List<Asset> edgeAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?",
List<Asset> edgeAssets = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/assets?",
new TypeReference<PageData<Asset>>() {}, new PageLink(100)).getData();
Assert.assertTrue(edgeAssets.contains(asset));
@ -323,15 +289,13 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
UUID ruleChainUUID = new UUID(ruleChainUpdateMsg.getIdMSB(), ruleChainUpdateMsg.getIdLSB());
RuleChain ruleChain = doGet("/api/ruleChain/" + ruleChainUUID.toString(), RuleChain.class);
Assert.assertNotNull(ruleChain);
List<RuleChain> edgeRuleChains = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/ruleChains?",
List<RuleChain> edgeRuleChains = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/ruleChains?",
new TypeReference<PageData<RuleChain>>() {}, new PageLink(100)).getData();
Assert.assertTrue(edgeRuleChains.contains(ruleChain));
testAutoGeneratedCodeByProtobuf(ruleChainUpdateMsg);
validateAdminSettings();
log.info("Received data checked");
}
private void validateAdminSettings() throws JsonProcessingException {
@ -367,39 +331,26 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertNotNull(jsonNode.get("test"));
}
private void testDevices() throws Exception {
log.info("Testing devices");
@Test
public void testDevices() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
Device savedDevice = saveDevice("Edge Device 2", "Default");
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/device/" + savedDevice.getId().getId().toString(), Device.class);
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType());
Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits());
Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits());
Assert.assertEquals(deviceUpdateMsg.getName(), savedDevice.getName());
Assert.assertEquals(deviceUpdateMsg.getType(), savedDevice.getType());
Device savedDevice = saveDeviceOnCloudAndVerifyDeliveryToEdge();
// 2
edgeImitator.expectMessageAmount(1);
doDelete("/api/edge/" + edge.getId().getId().toString()
+ "/device/" + savedDevice.getId().getId().toString(), Device.class);
doDelete("/api/edge/" + edge.getUuidId()
+ "/device/" + savedDevice.getUuidId(), Device.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, deviceUpdateMsg.getMsgType());
Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits());
Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits());
// 3
edgeImitator.expectMessageAmount(1);
doDelete("/api/device/" + savedDevice.getId().getId().toString())
doDelete("/api/device/" + savedDevice.getUuidId())
.andExpect(status().isOk());
// we should not get any message because device is not assigned to edge any more
Assert.assertFalse(edgeImitator.waitForMessages(1));
@ -407,8 +358,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 4
edgeImitator.expectMessageAmount(1);
savedDevice = saveDevice("Edge Device 3", "Default");
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/device/" + savedDevice.getId().getId().toString(), Device.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/device/" + savedDevice.getUuidId(), Device.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
@ -421,7 +372,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 5
edgeImitator.expectMessageAmount(1);
doDelete("/api/device/" + savedDevice.getId().getId().toString())
doDelete("/api/device/" + savedDevice.getUuidId())
.andExpect(status().isOk());
// in this case we should get messages because device was assigned to edge
Assert.assertTrue(edgeImitator.waitForMessages());
@ -432,17 +383,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits());
Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits());
log.info("Devices tested successfully");
}
private void testAssets() throws Exception {
log.info("Testing assets");
@Test
public void testAssets() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
Asset savedAsset = saveAsset("Edge Asset 2");
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/asset/" + savedAsset.getUuidId(), Asset.class);
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof AssetUpdateMsg);
@ -455,8 +404,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 2
edgeImitator.expectMessageAmount(1);
doDelete("/api/edge/" + edge.getId().getId().toString()
+ "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
doDelete("/api/edge/" + edge.getUuidId()
+ "/asset/" + savedAsset.getUuidId(), Asset.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof AssetUpdateMsg);
@ -467,15 +416,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 3
edgeImitator.expectMessageAmount(1);
doDelete("/api/asset/" + savedAsset.getId().getId().toString())
doDelete("/api/asset/" + savedAsset.getUuidId())
.andExpect(status().isOk());
Assert.assertFalse(edgeImitator.waitForMessages(1));
// 4
edgeImitator.expectMessageAmount(1);
savedAsset = saveAsset("Edge Asset 3");
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/asset/" + savedAsset.getId().getId().toString(), Asset.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/asset/" + savedAsset.getUuidId(), Asset.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof AssetUpdateMsg);
@ -488,7 +437,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 5
edgeImitator.expectMessageAmount(1);
doDelete("/api/asset/" + savedAsset.getId().getId().toString())
doDelete("/api/asset/" + savedAsset.getUuidId())
.andExpect(status().isOk());
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
@ -497,21 +446,18 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, assetUpdateMsg.getMsgType());
Assert.assertEquals(assetUpdateMsg.getIdMSB(), savedAsset.getUuidId().getMostSignificantBits());
Assert.assertEquals(assetUpdateMsg.getIdLSB(), savedAsset.getUuidId().getLeastSignificantBits());
log.info("Assets tested successfully");
}
private void testRuleChains() throws Exception {
log.info("Testing RuleChains");
@Test
public void testRuleChains() throws Exception {
// 1
edgeImitator.expectMessageAmount(2);
RuleChain ruleChain = new RuleChain();
ruleChain.setName("Edge Test Rule Chain");
ruleChain.setType(RuleChainType.EDGE);
RuleChain savedRuleChain = doPost("/api/ruleChain", ruleChain, RuleChain.class);
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/ruleChain/" + savedRuleChain.getUuidId(), RuleChain.class);
createRuleChainMetadata(savedRuleChain);
Assert.assertTrue(edgeImitator.waitForMessages());
Optional<RuleChainUpdateMsg> ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class);
@ -528,8 +474,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 3
edgeImitator.expectMessageAmount(1);
doDelete("/api/edge/" + edge.getId().getId().toString()
+ "/ruleChain/" + savedRuleChain.getId().getId().toString(), RuleChain.class);
doDelete("/api/edge/" + edge.getUuidId()
+ "/ruleChain/" + savedRuleChain.getUuidId(), RuleChain.class);
Assert.assertTrue(edgeImitator.waitForMessages());
ruleChainUpdateMsgOpt = edgeImitator.findMessageByType(RuleChainUpdateMsg.class);
Assert.assertTrue(ruleChainUpdateMsgOpt.isPresent());
@ -540,11 +486,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 4
edgeImitator.expectMessageAmount(1);
doDelete("/api/ruleChain/" + savedRuleChain.getId().getId().toString())
doDelete("/api/ruleChain/" + savedRuleChain.getUuidId())
.andExpect(status().isOk());
Assert.assertFalse(edgeImitator.waitForMessages(1));
log.info("RuleChains tested successfully");
}
private void testRuleChainMetadataRequestMsg(RuleChainId ruleChainId) throws Exception {
@ -608,16 +552,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
doPost("/api/ruleChain/metadata", ruleChainMetaData, RuleChainMetaData.class);
}
private void testDashboards() throws Exception {
log.info("Testing Dashboards");
@Test
public void testDashboards() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
Dashboard dashboard = new Dashboard();
dashboard.setTitle("Edge Test Dashboard");
Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class);
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/dashboard/" + savedDashboard.getUuidId(), Dashboard.class);
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg);
@ -641,8 +584,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 3
edgeImitator.expectMessageAmount(1);
doDelete("/api/edge/" + edge.getId().getId().toString()
+ "/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
doDelete("/api/edge/" + edge.getUuidId()
+ "/dashboard/" + savedDashboard.getUuidId(), Dashboard.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DashboardUpdateMsg);
@ -653,16 +596,13 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 4
edgeImitator.expectMessageAmount(1);
doDelete("/api/dashboard/" + savedDashboard.getId().getId().toString())
doDelete("/api/dashboard/" + savedDashboard.getUuidId())
.andExpect(status().isOk());
Assert.assertFalse(edgeImitator.waitForMessages(1));
log.info("Dashboards tested successfully");
}
private void testRelations() throws Exception {
log.info("Testing Relations");
@Test
public void testRelations() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
Device device = findDeviceByName("Edge Device 1");
@ -710,13 +650,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(relationUpdateMsg.getToIdLSB(), relation.getTo().getId().getLeastSignificantBits());
Assert.assertEquals(relationUpdateMsg.getToEntityType(), relation.getTo().getEntityType().name());
Assert.assertEquals(relationUpdateMsg.getTypeGroup(), relation.getTypeGroup().name());
log.info("Relations tested successfully");
}
private void testAlarms() throws Exception {
log.info("Testing Alarms");
@Test
public void testAlarms() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
Device device = findDeviceByName("Edge Device 1");
@ -739,7 +676,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 2
edgeImitator.expectMessageAmount(1);
doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/ack");
doPost("/api/alarm/" + savedAlarm.getUuidId() + "/ack");
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg);
@ -752,7 +689,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 3
edgeImitator.expectMessageAmount(1);
doPost("/api/alarm/" + savedAlarm.getId().getId().toString() + "/clear");
doPost("/api/alarm/" + savedAlarm.getUuidId() + "/clear");
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg);
@ -765,7 +702,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 4
edgeImitator.expectMessageAmount(1);
doDelete("/api/alarm/" + savedAlarm.getId().getId().toString())
doDelete("/api/alarm/" + savedAlarm.getUuidId())
.andExpect(status().isOk());
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
@ -776,13 +713,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(alarmUpdateMsg.getName(), savedAlarm.getName());
Assert.assertEquals(alarmUpdateMsg.getOriginatorName(), device.getName());
Assert.assertEquals(alarmUpdateMsg.getStatus(), AlarmStatus.CLEARED_ACK.name());
log.info("Alarms tested successfully");
}
private void testEntityView() throws Exception {
log.info("Testing EntityView");
@Test
public void testEntityView() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
Device device = findDeviceByName("Edge Device 1");
@ -791,8 +725,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
entityView.setType("test");
entityView.setEntityId(device.getId());
EntityView savedEntityView = doPost("/api/entityView", entityView, EntityView.class);
doPost("/api/edge/" + edge.getId().getId().toString()
+ "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class);
doPost("/api/edge/" + edge.getUuidId()
+ "/entityView/" + savedEntityView.getUuidId(), EntityView.class);
Assert.assertTrue(edgeImitator.waitForMessages());
verifyEntityViewUpdateMsg(savedEntityView, device);
@ -818,8 +752,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 3
edgeImitator.expectMessageAmount(1);
doDelete("/api/edge/" + edge.getId().getId().toString()
+ "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class);
doDelete("/api/edge/" + edge.getUuidId()
+ "/entityView/" + savedEntityView.getUuidId(), EntityView.class);
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof EntityViewUpdateMsg);
@ -830,11 +764,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
edgeImitator.expectMessageAmount(1);
doDelete("/api/entityView/" + savedEntityView.getId().getId().toString())
doDelete("/api/entityView/" + savedEntityView.getUuidId())
.andExpect(status().isOk());
Assert.assertFalse(edgeImitator.waitForMessages(1));
log.info("EntityView tested successfully");
}
private void verifyEntityViewUpdateMsg(EntityView entityView, Device device) {
@ -851,16 +783,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(entityViewUpdateMsg.getEntityType().name(), device.getId().getEntityType().name());
}
private void testCustomerAndNewUser() throws Exception {
log.info("Testing Customer");
@Test
public void testCustomerAndNewUser() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
Customer customer = new Customer();
customer.setTitle("Edge Customer 1");
Customer savedCustomer = doPost("/api/customer", customer, Customer.class);
doPost("/api/customer/" + savedCustomer.getId().getId().toString()
+ "/edge/" + edge.getId().getId().toString(), Edge.class);
doPost("/api/customer/" + savedCustomer.getUuidId()
+ "/edge/" + edge.getUuidId(), Edge.class);
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg);
@ -893,7 +824,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 3
edgeImitator.expectMessageAmount(1);
doDelete("/api/customer/edge/" + edge.getId().getId().toString(), Edge.class);
doDelete("/api/customer/edge/" + edge.getUuidId(), Edge.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof CustomerUpdateMsg);
@ -903,16 +834,13 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(customerUpdateMsg.getIdLSB(), savedCustomer.getUuidId().getLeastSignificantBits());
edgeImitator.expectMessageAmount(1);
doDelete("/api/customer/" + savedCustomer.getId().getId().toString())
doDelete("/api/customer/" + savedCustomer.getUuidId())
.andExpect(status().isOk());
Assert.assertFalse(edgeImitator.waitForMessages(1));
log.info("Customer tested successfully");
}
private void testWidgetsBundleAndWidgetType() throws Exception {
log.info("Testing WidgetsBundle and WidgetType");
@Test
public void testWidgetsBundleAndWidgetType() throws Exception {
// 1
edgeImitator.expectMessageAmount(1);
WidgetsBundle widgetsBundle = new WidgetsBundle();
@ -951,7 +879,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 3
edgeImitator.expectMessageAmount(1);
doDelete("/api/widgetType/" + savedWidgetType.getId().getId().toString())
doDelete("/api/widgetType/" + savedWidgetType.getUuidId())
.andExpect(status().isOk());
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
@ -963,7 +891,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
// 4
edgeImitator.expectMessageAmount(1);
doDelete("/api/widgetsBundle/" + savedWidgetsBundle.getId().getId().toString())
doDelete("/api/widgetsBundle/" + savedWidgetsBundle.getUuidId())
.andExpect(status().isOk());
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
@ -972,13 +900,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, widgetsBundleUpdateMsg.getMsgType());
Assert.assertEquals(widgetsBundleUpdateMsg.getIdMSB(), savedWidgetsBundle.getUuidId().getMostSignificantBits());
Assert.assertEquals(widgetsBundleUpdateMsg.getIdLSB(), savedWidgetsBundle.getUuidId().getLeastSignificantBits());
log.info("WidgetsBundle and WidgetType tested successfully");
}
private void testTimeseries() throws Exception {
log.info("Testing timeseries");
@Test
public void testTimeseries() throws Exception {
edgeImitator.expectMessageAmount(1);
Device device = findDeviceByName("Edge Device 1");
String timeseriesData = "{\"data\":{\"temperature\":25},\"ts\":" + System.currentTimeMillis() + "}";
@ -1004,18 +929,15 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
TransportProtos.KeyValueProto keyValueProto = tsKvListProto.getKv(0);
Assert.assertEquals("temperature", keyValueProto.getKey());
Assert.assertEquals(25, keyValueProto.getLongV());
log.info("Timeseries tested successfully");
}
private void testAttributes() throws Exception {
log.info("Testing attributes");
@Test
public void testAttributes() throws Exception {
Device device = findDeviceByName("Edge Device 1");
testAttributesUpdatedMsg(device);
testPostAttributesMsg(device);
testAttributesDeleteMsg(device);
log.info("Attributes tested successfully");
}
private void testAttributesUpdatedMsg(Device device) throws JsonProcessingException, InterruptedException {
@ -1094,7 +1016,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals("key2", attributeDeleteMsg.getAttributeNames(1));
}
private void testRpcCall() throws Exception {
@Test
public void testRpcCall() throws Exception {
Device device = findDeviceByName("Edge Device 1");
ObjectNode body = mapper.createObjectNode();
@ -1117,9 +1040,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals("test_method", latestDeviceRpcCallMsg.getRequestMsg().getMethod());
}
private void testTimeseriesWithFailures() throws Exception {
log.info("Testing timeseries with failures");
@Test
public void testTimeseriesWithFailures() throws Exception {
int numberOfTimeseriesToSend = 1000;
edgeImitator.setRandomFailuresOnTimeseriesDownlink(true);
@ -1147,7 +1069,6 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
}
edgeImitator.setRandomFailuresOnTimeseriesDownlink(false);
log.info("Timeseries with failures tested successfully");
}
private boolean isIdxExistsInTheDownlinkList(int idx, List<EntityDataProto> allTelemetryMsgs) {
@ -1165,25 +1086,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
return false;
}
private void testSendMessagesToCloud() throws Exception {
log.info("Sending messages to cloud");
sendDevice();
sendDeviceWithNameThatAlreadyExistsOnCloud();
sendRelationRequest();
sendAlarm();
sendTelemetry();
sendRelation();
sendDeleteDeviceOnEdge();
sendRuleChainMetadataRequest();
sendUserCredentialsRequest();
sendDeviceCredentialsRequest();
sendDeviceRpcResponse();
sendDeviceCredentialsUpdate();
sendAttributesRequest();
log.info("Messages were sent successfully");
}
private void sendDevice() throws Exception {
@Test
public void testSendDeviceToCloud() throws Exception {
UUID uuid = Uuids.timeBased();
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
@ -1218,7 +1122,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals("Edge Device 2", device.getName());
}
private void sendDeviceWithNameThatAlreadyExistsOnCloud() throws Exception {
@Test
public void testSendDeviceToCloudWithNameThatAlreadyExistsOnCloud() throws Exception {
String deviceOnCloudName = RandomStringUtils.randomAlphanumeric(15);
Device deviceOnCloud = saveDevice(deviceOnCloudName, "Default");
@ -1270,7 +1175,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertNotEquals(deviceOnCloudName, device.getName());
}
private void sendRelationRequest() throws Exception {
@Test
public void testSendRelationRequestToCloud() throws Exception {
Device device = findDeviceByName("Edge Device 1");
Asset asset = findAssetByName("Edge Asset 1");
@ -1317,8 +1223,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(relation.getTypeGroup().name(), relationUpdateMsg.getTypeGroup());
}
private void sendAlarm() throws Exception {
Device device = findDeviceByName("Edge Device 2");
@Test
public void testSendAlarmToCloud() throws Exception {
Device device = saveDeviceOnCloudAndVerifyDeliveryToEdge();
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
AlarmUpdateMsg.Builder alarmUpdateMgBuilder = AlarmUpdateMsg.newBuilder();
@ -1339,7 +1246,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
List<AlarmInfo> alarms = doGetTypedWithPageLink("/api/alarm/{entityType}/{entityId}?",
new TypeReference<PageData<AlarmInfo>>() {},
new PageLink(100), device.getId().getEntityType().name(), device.getId().getId().toString())
new PageLink(100), device.getId().getEntityType().name(), device.getUuidId())
.getData();
Optional<AlarmInfo> foundAlarm = alarms.stream().filter(alarm -> alarm.getType().equals("alarm from edge")).findAny();
Assert.assertTrue(foundAlarm.isPresent());
@ -1349,12 +1256,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(AlarmSeverity.CRITICAL, alarmInfo.getSeverity());
}
private void sendTelemetry() throws Exception {
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?",
new TypeReference<PageData<Device>>() {}, new PageLink(100)).getData();
Optional<Device> foundDevice = edgeDevices.stream().filter(device1 -> device1.getName().equals("Edge Device 2")).findAny();
Assert.assertTrue(foundDevice.isPresent());
Device device = foundDevice.get();
@Test
public void testSendTelemetryToCloud() throws Exception {
Device device = saveDeviceOnCloudAndVerifyDeliveryToEdge();
edgeImitator.expectResponsesAmount(2);
@ -1402,7 +1306,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(1, timeseries.get(timeseriesKey).size());
Assert.assertEquals(timeseriesValue, timeseries.get(timeseriesKey).get(0).get("value"));
List<Map<String, String>> attributes = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + device.getId() + "/values/attributes/" + DataConstants.SERVER_SCOPE, new TypeReference<>() {});
String attributeValuesUrl = "/api/plugins/telemetry/DEVICE/" + device.getId() + "/values/attributes/" + DataConstants.SERVER_SCOPE;
List<Map<String, String>> attributes = doGetAsyncTyped(attributeValuesUrl, new TypeReference<>() {});
Assert.assertEquals(2, attributes.size());
var result = attributes.stream().filter(kv -> kv.get("key").equals(attributesKey)).filter(kv -> kv.get("value").equals(attributesValue)).findFirst();
Assert.assertTrue(result.isPresent());
@ -1413,15 +1318,10 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
new TypeReference<>() {});
}
private void sendRelation() throws Exception {
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?",
new TypeReference<PageData<Device>>() {}, new PageLink(100)).getData();
Optional<Device> foundDevice1 = edgeDevices.stream().filter(device1 -> device1.getName().equals("Edge Device 1")).findAny();
Assert.assertTrue(foundDevice1.isPresent());
Device device1 = foundDevice1.get();
Optional<Device> foundDevice2 = edgeDevices.stream().filter(device2 -> device2.getName().equals("Edge Device 2")).findAny();
Assert.assertTrue(foundDevice2.isPresent());
Device device2 = foundDevice2.get();
@Test
public void testSendRelationToCloud() throws Exception {
Device device1 = saveDeviceOnCloudAndVerifyDeliveryToEdge();
Device device2 = saveDeviceOnCloudAndVerifyDeliveryToEdge();
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
RelationUpdateMsg.Builder relationUpdateMsgBuilder = RelationUpdateMsg.newBuilder();
@ -1444,17 +1344,18 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertTrue(edgeImitator.waitForResponses());
EntityRelation relation = doGet("/api/relation?" +
"&fromId=" + device2.getId().getId().toString() +
"&fromId=" + device2.getUuidId() +
"&fromType=" + device2.getId().getEntityType().name() +
"&relationType=" + "test" +
"&relationTypeGroup=" + RelationTypeGroup.COMMON.name() +
"&toId=" + device1.getId().getId().toString() +
"&toId=" + device1.getUuidId() +
"&toType=" + device1.getId().getEntityType().name(), EntityRelation.class);
Assert.assertNotNull(relation);
}
private void sendDeleteDeviceOnEdge() throws Exception {
Device device = findDeviceByName("Edge Device 2");
@Test
public void testSendDeleteDeviceOnEdgeToCloud() throws Exception {
Device device = saveDeviceOnCloudAndVerifyDeliveryToEdge();
UplinkMsg.Builder upLinkMsgBuilder = UplinkMsg.newBuilder();
DeviceUpdateMsg.Builder deviceDeleteMsgBuilder = DeviceUpdateMsg.newBuilder();
deviceDeleteMsgBuilder.setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE);
@ -1468,15 +1369,16 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
edgeImitator.expectResponsesAmount(1);
edgeImitator.sendUplinkMsg(upLinkMsgBuilder.build());
Assert.assertTrue(edgeImitator.waitForResponses());
device = doGet("/api/device/" + device.getId().getId().toString(), Device.class);
device = doGet("/api/device/" + device.getUuidId(), Device.class);
Assert.assertNotNull(device);
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?",
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/devices?",
new TypeReference<PageData<Device>>() {
}, new PageLink(100)).getData();
Assert.assertFalse(edgeDevices.contains(device));
}
private void sendRuleChainMetadataRequest() throws Exception {
@Test
public void testSendRuleChainMetadataRequestToCloud() throws Exception {
RuleChainId edgeRootRuleChainId = edge.getRootRuleChainId();
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
@ -1503,7 +1405,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
testAutoGeneratedCodeByProtobuf(ruleChainMetadataUpdateMsg);
}
private void sendUserCredentialsRequest() throws Exception {
@Test
public void testSendUserCredentialsRequestToCloud() throws Exception {
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
UserCredentialsRequestMsg.Builder userCredentialsRequestMsgBuilder = UserCredentialsRequestMsg.newBuilder();
userCredentialsRequestMsgBuilder.setUserIdMSB(tenantAdmin.getId().getId().getMostSignificantBits());
@ -1528,10 +1431,11 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
testAutoGeneratedCodeByProtobuf(userCredentialsUpdateMsg);
}
private void sendDeviceCredentialsRequest() throws Exception {
@Test
public void testSendDeviceCredentialsRequestToCloud() throws Exception {
Device device = findDeviceByName("Edge Device 1");
DeviceCredentials deviceCredentials = doGet("/api/device/" + device.getId().getId().toString() + "/credentials", DeviceCredentials.class);
DeviceCredentials deviceCredentials = doGet("/api/device/" + device.getUuidId() + "/credentials", DeviceCredentials.class);
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
DeviceCredentialsRequestMsg.Builder deviceCredentialsRequestMsgBuilder = DeviceCredentialsRequestMsg.newBuilder();
@ -1557,7 +1461,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(deviceCredentialsUpdateMsg.getCredentialsId(), deviceCredentials.getCredentialsId());
}
private void sendDeviceRpcResponse() throws Exception {
@Test
public void testSendDeviceRpcResponseToCloud() throws Exception {
Device device = findDeviceByName("Edge Device 1");
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
@ -1582,7 +1487,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertTrue(edgeImitator.waitForResponses());
}
private void sendDeviceCredentialsUpdate() throws Exception {
@Test
public void testSendDeviceCredentialsUpdateToCloud() throws Exception {
Device device = findDeviceByName("Edge Device 1");
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
@ -1601,24 +1507,30 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertTrue(edgeImitator.waitForResponses());
}
private void sendAttributesRequest() throws Exception {
@Test
public void testSendAttributesRequestToCloud() throws Exception {
Device device = findDeviceByName("Edge Device 1");
sendAttributesRequest(device, DataConstants.SERVER_SCOPE, "{\"key1\":\"value1\"}",
"key1", "value1", 2);
sendAttributesRequest(device, DataConstants.SHARED_SCOPE, "{\"key2\":\"value2\"}",
"key2", "value2", 1);
sendAttributesRequestAndVerify(device, DataConstants.SERVER_SCOPE, "{\"key1\":\"value1\"}",
"key1", "value1");
sendAttributesRequestAndVerify(device, DataConstants.SHARED_SCOPE, "{\"key2\":\"value2\"}",
"key2", "value2");
}
private void sendAttributesRequest(Device device, String scope, String attributesDataStr, String expectedKey,
String expectedValue, int expectedSize) throws Exception {
private void sendAttributesRequestAndVerify(Device device, String scope, String attributesDataStr, String expectedKey,
String expectedValue) throws Exception {
JsonNode attributesData = mapper.readTree(attributesDataStr);
doPost("/api/plugins/telemetry/DEVICE/" + device.getId().getId().toString() + "/attributes/" + scope,
doPost("/api/plugins/telemetry/DEVICE/" + device.getUuidId() + "/attributes/" + scope,
attributesData);
// Wait before device attributes saved to database before requesting them from edge
// queue used to save attributes to database
Thread.sleep(500);
Awaitility.await()
.atMost(10, TimeUnit.SECONDS)
.until(() -> {
String urlTemplate = "/api/plugins/telemetry/DEVICE/" + device.getId() + "/keys/attributes/" + scope;
List<String> actualKeys = doGetAsyncTyped(urlTemplate, new TypeReference<>() {});
return actualKeys != null && !actualKeys.isEmpty() && actualKeys.contains(expectedKey);
});
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
AttributesRequestMsg.Builder attributesRequestMsgBuilder = AttributesRequestMsg.newBuilder();
@ -1646,19 +1558,39 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertTrue(latestEntityDataMsg.hasAttributesUpdatedMsg());
TransportProtos.PostAttributeMsg attributesUpdatedMsg = latestEntityDataMsg.getAttributesUpdatedMsg();
Assert.assertEquals(expectedSize, attributesUpdatedMsg.getKvList().size());
boolean found = false;
for (TransportProtos.KeyValueProto keyValueProto : attributesUpdatedMsg.getKvList()) {
if (keyValueProto.getKey().equals(expectedKey)) {
Assert.assertEquals(expectedKey, keyValueProto.getKey());
Assert.assertEquals(expectedValue, keyValueProto.getStringV());
found = true;
}
}
Assert.assertTrue("Expected key and value must be found", found);
}
// Utility methods
private Device saveDeviceOnCloudAndVerifyDeliveryToEdge() throws Exception {
edgeImitator.expectMessageAmount(1);
Device savedDevice = saveDevice(RandomStringUtils.randomAlphanumeric(15), "Default");
doPost("/api/edge/" + edge.getUuidId()
+ "/device/" + savedDevice.getUuidId(), Device.class);
Assert.assertTrue(edgeImitator.waitForMessages());
AbstractMessage latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof DeviceUpdateMsg);
DeviceUpdateMsg deviceUpdateMsg = (DeviceUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceUpdateMsg.getMsgType());
Assert.assertEquals(deviceUpdateMsg.getIdMSB(), savedDevice.getUuidId().getMostSignificantBits());
Assert.assertEquals(deviceUpdateMsg.getIdLSB(), savedDevice.getUuidId().getLeastSignificantBits());
Assert.assertEquals(deviceUpdateMsg.getName(), savedDevice.getName());
Assert.assertEquals(deviceUpdateMsg.getType(), savedDevice.getType());
return savedDevice;
}
private Device findDeviceByName(String deviceName) throws Exception {
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/devices?",
List<Device> edgeDevices = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/devices?",
new TypeReference<PageData<Device>>() {
}, new PageLink(100)).getData();
Optional<Device> foundDevice = edgeDevices.stream().filter(d -> d.getName().equals(deviceName)).findAny();
@ -1669,7 +1601,7 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
}
private Asset findAssetByName(String assetName) throws Exception {
List<Asset> edgeAssets = doGetTypedWithPageLink("/api/edge/" + edge.getId().getId().toString() + "/assets?",
List<Asset> edgeAssets = doGetTypedWithPageLink("/api/edge/" + edge.getUuidId() + "/assets?",
new TypeReference<PageData<Asset>>() {
}, new PageLink(100)).getData();

20
common/data/src/main/java/org/thingsboard/server/common/data/edge/Edge.java

@ -57,12 +57,6 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
@NoXss
@Length(fieldName = "secret")
private String secret;
@NoXss
@Length(fieldName = "edgeLicenseKey", max = 30)
private String edgeLicenseKey;
@NoXss
@Length(fieldName = "cloudEndpoint")
private String cloudEndpoint;
public Edge() {
super();
@ -82,8 +76,6 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
this.name = edge.getName();
this.routingKey = edge.getRoutingKey();
this.secret = edge.getSecret();
this.edgeLicenseKey = edge.getEdgeLicenseKey();
this.cloudEndpoint = edge.getCloudEndpoint();
}
public void update(Edge edge) {
@ -95,8 +87,6 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
this.name = edge.getName();
this.routingKey = edge.getRoutingKey();
this.secret = edge.getSecret();
this.edgeLicenseKey = edge.getEdgeLicenseKey();
this.cloudEndpoint = edge.getCloudEndpoint();
}
@ApiModelProperty(position = 1, value = "JSON object with the Edge Id. " +
@ -162,14 +152,4 @@ public class Edge extends SearchTextBasedWithAdditionalInfo<EdgeId> implements H
return this.secret;
}
@ApiModelProperty(position = 11, required = true, value = "Edge license key obtained from license portal", example = "AgcnI24Z06XC&m6Sxsdgf")
public String getEdgeLicenseKey() {
return this.edgeLicenseKey;
}
@ApiModelProperty(position = 12, required = true, value = "Edge uses this cloud URL to activate and periodically check it's license", example = "https://thingsboard.cloud")
public String getCloudEndpoint() {
return this.cloudEndpoint;
}
}

4
common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java

@ -162,7 +162,9 @@ public class EdgeGrpcClient implements EdgeRpcClient {
public void disconnect(boolean onError) throws InterruptedException {
if (!onError) {
try {
inputStream.onCompleted();
if (inputStream != null) {
inputStream.onCompleted();
}
} catch (Exception e) {
log.error("Exception during onCompleted", e);
}

6
common/edge-api/src/main/proto/edge.proto

@ -99,10 +99,8 @@ message EdgeConfiguration {
string type = 8;
string routingKey = 9;
string secret = 10;
string edgeLicenseKey = 11;
string cloudEndpoint = 12;
string additionalInfo = 13;
string cloudType = 14;
string additionalInfo = 11;
string cloudType = 12;
}
enum UpdateMsgType {

6
dao/src/main/java/org/thingsboard/server/dao/edge/EdgeServiceImpl.java

@ -404,12 +404,6 @@ public class EdgeServiceImpl extends AbstractEntityService implements EdgeServic
if (StringUtils.isEmpty(edge.getRoutingKey())) {
throw new DataValidationException("Edge routing key should be specified!");
}
if (StringUtils.isEmpty(edge.getEdgeLicenseKey())) {
throw new DataValidationException("Edge license key should be specified!");
}
if (StringUtils.isEmpty(edge.getCloudEndpoint())) {
throw new DataValidationException("Cloud endpoint should be specified!");
}
if (edge.getTenantId() == null) {
throw new DataValidationException("Edge should be assigned to tenant!");
} else {

2
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -544,8 +544,6 @@ public class ModelConstants {
public static final String EDGE_ROUTING_KEY_PROPERTY = "routing_key";
public static final String EDGE_SECRET_PROPERTY = "secret";
public static final String EDGE_LICENSE_KEY_PROPERTY = "edge_license_key";
public static final String EDGE_CLOUD_ENDPOINT_KEY_PROPERTY = "cloud_endpoint";
/**
* Edge queue constants.

14
dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractEdgeEntity.java

@ -35,10 +35,8 @@ import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_CLOUD_ENDPOINT_KEY_PROPERTY;
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_LICENSE_KEY_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_NAME_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROOT_RULE_CHAIN_ID_PROPERTY;
import static org.thingsboard.server.dao.model.ModelConstants.EDGE_ROUTING_KEY_PROPERTY;
@ -80,12 +78,6 @@ public abstract class AbstractEdgeEntity<T extends Edge> extends BaseSqlEntity<T
@Column(name = EDGE_SECRET_PROPERTY)
private String secret;
@Column(name = EDGE_LICENSE_KEY_PROPERTY)
private String edgeLicenseKey;
@Column(name = EDGE_CLOUD_ENDPOINT_KEY_PROPERTY)
private String cloudEndpoint;
@Type(type = "json")
@Column(name = ModelConstants.EDGE_ADDITIONAL_INFO_PROPERTY)
private JsonNode additionalInfo;
@ -113,8 +105,6 @@ public abstract class AbstractEdgeEntity<T extends Edge> extends BaseSqlEntity<T
this.label = edge.getLabel();
this.routingKey = edge.getRoutingKey();
this.secret = edge.getSecret();
this.edgeLicenseKey = edge.getEdgeLicenseKey();
this.cloudEndpoint = edge.getCloudEndpoint();
this.additionalInfo = edge.getAdditionalInfo();
}
@ -130,8 +120,6 @@ public abstract class AbstractEdgeEntity<T extends Edge> extends BaseSqlEntity<T
this.searchText = edgeEntity.getSearchText();
this.routingKey = edgeEntity.getRoutingKey();
this.secret = edgeEntity.getSecret();
this.edgeLicenseKey = edgeEntity.getEdgeLicenseKey();
this.cloudEndpoint = edgeEntity.getCloudEndpoint();
this.additionalInfo = edgeEntity.getAdditionalInfo();
}
@ -166,8 +154,6 @@ public abstract class AbstractEdgeEntity<T extends Edge> extends BaseSqlEntity<T
edge.setLabel(label);
edge.setRoutingKey(routingKey);
edge.setSecret(secret);
edge.setEdgeLicenseKey(edgeLicenseKey);
edge.setCloudEndpoint(cloudEndpoint);
edge.setAdditionalInfo(additionalInfo);
return edge;
}

2
dao/src/main/resources/sql/schema-entities.sql

@ -601,8 +601,6 @@ CREATE TABLE IF NOT EXISTS edge (
label varchar(255),
routing_key varchar(255),
secret varchar(255),
edge_license_key varchar(30),
cloud_endpoint varchar(255),
search_text varchar(255),
tenant_id uuid,
CONSTRAINT edge_name_unq_key UNIQUE (tenant_id, name),

2
dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java

@ -249,8 +249,6 @@ public abstract class AbstractServiceTest {
edge.setType(type);
edge.setSecret(RandomStringUtils.randomAlphanumeric(20));
edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20));
edge.setEdgeLicenseKey(RandomStringUtils.randomAlphanumeric(20));
edge.setCloudEndpoint("http://localhost:8080");
return edge;
}
}

4
dao/src/test/java/org/thingsboard/server/dao/service/BaseDashboardServiceTest.java

@ -32,13 +32,11 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.dao.exception.DataValidationException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
@ -420,8 +418,6 @@ public abstract class BaseDashboardServiceTest extends AbstractServiceTest {
edge.setType("default");
edge.setSecret(RandomStringUtils.randomAlphanumeric(20));
edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20));
edge.setEdgeLicenseKey(RandomStringUtils.randomAlphanumeric(20));
edge.setCloudEndpoint("http://localhost:8080");
edge = edgeService.saveEdge(edge, true);
try {
dashboardService.assignDashboardToEdge(tenantId, dashboard.getId(), edge.getId());

2
dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java

@ -314,8 +314,6 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest {
edge.setLabel("EdgeLabel" + i);
edge.setSecret(RandomStringUtils.randomAlphanumeric(20));
edge.setRoutingKey(RandomStringUtils.randomAlphanumeric(20));
edge.setEdgeLicenseKey(RandomStringUtils.randomAlphanumeric(20));
edge.setCloudEndpoint("http://localhost:8080");
return edge;
}

10
ui-ngx/src/app/core/http/entity.service.ts

@ -1050,8 +1050,6 @@ export class EntityService {
additionalInfo: {
description: edgeEntityData.description
},
edgeLicenseKey: edgeEntityData.edgeLicenseKey,
cloudEndpoint: edgeEntityData.cloudEndpoint !== '' ? edgeEntityData.cloudEndpoint : window.location.origin,
routingKey: edgeEntityData.routingKey !== '' ? edgeEntityData.routingKey : guid(),
secret: edgeEntityData.secret !== '' ? edgeEntityData.secret : generateSecret(20)
};
@ -1099,8 +1097,6 @@ export class EntityService {
const edgeEntityData: EdgeImportEntityData = entityData as EdgeImportEntityData;
if (result.label !== edgeEntityData.label ||
result.type !== edgeEntityData.type ||
(edgeEntityData.cloudEndpoint !== '' && result.cloudEndpoint !== edgeEntityData.cloudEndpoint) ||
(edgeEntityData.edgeLicenseKey !== '' && result.edgeLicenseKey !== edgeEntityData.edgeLicenseKey) ||
(edgeEntityData.routingKey !== '' && result.routingKey !== edgeEntityData.routingKey) ||
(edgeEntityData.secret !== '' && result.secret !== edgeEntityData.secret) ||
additionalInfo.description !== edgeEntityData.description) {
@ -1108,12 +1104,6 @@ export class EntityService {
result.type = edgeEntityData.type;
result.additionalInfo = additionalInfo;
result.additionalInfo.description = edgeEntityData.description;
if (edgeEntityData.cloudEndpoint !== '') {
result.cloudEndpoint = edgeEntityData.cloudEndpoint;
}
if (edgeEntityData.edgeLicenseKey !== '') {
result.edgeLicenseKey = edgeEntityData.edgeLicenseKey;
}
if (edgeEntityData.routingKey !== '') {
result.routingKey = edgeEntityData.routingKey;
}

4
ui-ngx/src/app/modules/home/components/import-export/import-export.models.ts

@ -66,8 +66,6 @@ export enum ImportEntityColumnType {
lwm2mServerClientSecretKey = 'LWM2M_SERVER_CLIENT_SECRET_KEY',
isGateway = 'IS_GATEWAY',
description = 'DESCRIPTION',
edgeLicenseKey = 'EDGE_LICENSE_KEY',
cloudEndpoint = 'CLOUD_ENDPOINT',
routingKey = 'ROUTING_KEY',
secret = 'SECRET'
}
@ -102,8 +100,6 @@ export const importEntityColumnTypeTranslations = new Map<ImportEntityColumnType
[ImportEntityColumnType.lwm2mServerClientSecretKey, 'import.column-type.lwm2m.lwm2m-server-secret-key'],
[ImportEntityColumnType.isGateway, 'import.column-type.isgateway'],
[ImportEntityColumnType.description, 'import.column-type.description'],
[ImportEntityColumnType.edgeLicenseKey, 'import.column-type.edge-license-key'],
[ImportEntityColumnType.cloudEndpoint, 'import.column-type.cloud-endpoint'],
[ImportEntityColumnType.routingKey, 'import.column-type.routing-key'],
[ImportEntityColumnType.secret, 'import.column-type.secret']
]

12
ui-ngx/src/app/modules/home/components/import-export/table-columns-assignment.component.ts

@ -116,8 +116,6 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
break;
case EntityType.EDGE:
this.columnTypes.push(
{ value: ImportEntityColumnType.edgeLicenseKey },
{ value: ImportEntityColumnType.cloudEndpoint },
{ value: ImportEntityColumnType.routingKey },
{ value: ImportEntityColumnType.secret }
);
@ -145,8 +143,6 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
const isSelectType = this.columns.findIndex((column) => column.type === ImportEntityColumnType.type) > -1;
const isSelectLabel = this.columns.findIndex((column) => column.type === ImportEntityColumnType.label) > -1;
const isSelectDescription = this.columns.findIndex((column) => column.type === ImportEntityColumnType.description) > -1;
const isSelectEdgeLicenseKey = this.columns.findIndex((column) => column.type === ImportEntityColumnType.edgeLicenseKey) > -1;
const isSelectCloudEndpoint = this.columns.findIndex((column) => column.type === ImportEntityColumnType.cloudEndpoint) > -1;
const isSelectRoutingKey = this.columns.findIndex((column) => column.type === ImportEntityColumnType.routingKey) > -1;
const isSelectSecret = this.columns.findIndex((column) => column.type === ImportEntityColumnType.secret) > -1;
const hasInvalidColumn = this.columns.findIndex((column) => !this.columnValid(column)) > -1;
@ -171,14 +167,6 @@ export class TableColumnsAssignmentComponent implements OnInit, ControlValueAcce
});
}
const edgeLicenseKeyColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.edgeLicenseKey);
if (edgeLicenseKeyColumnType) {
edgeLicenseKeyColumnType.disabled = isSelectEdgeLicenseKey;
}
const cloudEndpointColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.cloudEndpoint);
if (cloudEndpointColumnType) {
cloudEndpointColumnType.disabled = isSelectCloudEndpoint;
}
const routingKeyColumnType = this.columnTypes.find((columnType) => columnType.value === ImportEntityColumnType.routingKey);
if (routingKeyColumnType) {
routingKeyColumnType.disabled = isSelectRoutingKey;

26
ui-ngx/src/app/modules/home/pages/edge/edge.component.html

@ -141,32 +141,6 @@
[required]="true"
[entityType]="entityType.EDGE">
</tb-entity-subtype-autocomplete>
<div [fxShow]="edgeScope !== 'customer_user'">
<div class="tb-hint" [innerHTML]="'edge.edge-license-key-hint' | translate"></div>
<mat-form-field class="mat-block">
<mat-label translate>edge.edge-license-key</mat-label>
<input matInput formControlName="edgeLicenseKey" required>
<mat-error *ngIf="entityForm.get('edgeLicenseKey').hasError('required')">
{{ 'edge.edge-license-key-required' | translate }}
</mat-error>
<mat-error *ngIf="entityForm.get('edgeLicenseKey').hasError('maxlength')">
{{ 'edge.edge-license-key-max-length' | translate }}
</mat-error>
</mat-form-field>
</div>
<div [fxShow]="edgeScope !== 'customer_user'">
<div translate class="tb-hint">edge.cloud-endpoint-hint</div>
<mat-form-field class="mat-block">
<mat-label translate>edge.cloud-endpoint</mat-label>
<input matInput formControlName="cloudEndpoint" required>
<mat-error *ngIf="entityForm.get('cloudEndpoint').hasError('required')">
{{ 'edge.cloud-endpoint-required' | translate }}
</mat-error>
<mat-error *ngIf="entityForm.get('cloudEndpoint').hasError('maxlength')">
{{ 'edge.cloud-endpoint-max-length' | translate }}
</mat-error>
</mat-form-field>
</div>
</fieldset>
<div fxLayout="row" [fxShow]="edgeScope !== 'customer_user'">
<mat-form-field class="mat-block" fxFlex>

7
ui-ngx/src/app/modules/home/pages/edge/edge.component.ts

@ -49,9 +49,6 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
ngOnInit() {
this.edgeScope = this.entitiesTableConfig.componentsData.edgeScope;
this.entityForm.patchValue({
cloudEndpoint: window.location.origin
});
super.ngOnInit();
}
@ -73,8 +70,6 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
name: [entity ? entity.name : '', [Validators.required, Validators.maxLength(255)]],
type: [entity?.type ? entity.type : 'default', [Validators.required, Validators.maxLength(255)]],
label: [entity ? entity.label : '', Validators.maxLength(255)],
cloudEndpoint: [null, [Validators.required, Validators.maxLength(255)]],
edgeLicenseKey: ['', [Validators.required, Validators.maxLength(30)]],
routingKey: this.fb.control({value: entity ? entity.routingKey : null, disabled: true}),
secret: this.fb.control({value: entity ? entity.secret : null, disabled: true}),
additionalInfo: this.fb.group(
@ -93,8 +88,6 @@ export class EdgeComponent extends EntityComponent<EdgeInfo> {
name: entity.name,
type: entity.type,
label: entity.label,
cloudEndpoint: entity.cloudEndpoint ? entity.cloudEndpoint : window.location.origin,
edgeLicenseKey: entity.edgeLicenseKey,
routingKey: entity.routingKey,
secret: entity.secret,
additionalInfo: {

2
ui-ngx/src/app/shared/models/edge.models.ts

@ -30,8 +30,6 @@ export interface Edge extends BaseData<EdgeId> {
type: string;
secret: string;
routingKey: string;
cloudEndpoint: string;
edgeLicenseKey: string;
label?: string;
additionalInfo?: any;
rootRuleChainId?: RuleChainId;

2
ui-ngx/src/app/shared/models/entity.models.ts

@ -56,8 +56,6 @@ export interface ImportEntityData {
export interface EdgeImportEntityData extends ImportEntityData {
secret: string;
routingKey: string;
cloudEndpoint: string;
edgeLicenseKey: string;
}
export interface ImportEntitiesResultInfo {

8
ui-ngx/src/assets/locale/locale.constant-cs_CZ.json

@ -1389,12 +1389,6 @@
"name": "Název",
"name-starts-with": "Název edge začíná",
"name-required": "Název je povinný.",
"edge-license-key": "Licenční klíč edge",
"edge-license-key-required": "Licenční klíč edge je povinný.",
"edge-license-key-hint": "Pro získání licence jděte na <a href='https://thingsboard.io/pricing/?active=thingsboard-edge' target='_blank'>pricing page</a> a vyberte is vhodnou licenci.",
"cloud-endpoint": "Cloud Endpoint",
"cloud-endpoint-required": "Cloud Endpoint je povinný.",
"cloud-endpoint-hint": "Edge vyžaduje HTTP(s) přístup do Cloudu (ThingsBoard CE/PE) pro ověření licenčního klíče. Zadejte prosím Cloud URL, ke které se může edge připojit.",
"description": "Popis",
"details": "Detail",
"events": "Události",
@ -2168,8 +2162,6 @@
"isgateway": "Je bránou",
"activity-time-from-gateway-device": "Čas aktivity ze zařízení brány",
"description": "Popis",
"edge-license-key": "Licenční klíč",
"cloud-endpoint": "Cloud Endpoint",
"routing-key": "Klíč edge",
"secret": "Edge secret"
},

6
ui-ngx/src/assets/locale/locale.constant-de_DE.json

@ -752,12 +752,6 @@
"name": "Name",
"name-starts-with": "Der Kantenname beginnt mit",
"name-required": "Name ist erforderlich.",
"edge-license-key": "Edge Lizenzschlüssel",
"edge-license-key-required": "Edge Lizenzschlüssel ist erforderlich.",
"edge-license-key-hint": "Um Ihre Lizenz zu erhalten, navigieren Sie zur <a href='https://thingsboard.io/pricing/?active=thingsboard-edge'arget='_blank'> Preisseite </a> und wählen Sie die beste Lizenzoption für Ihre aus Fall.",
"cloud-endpoint": "Cloud-Endpunkt",
"cloud-endpoint-required": "Cloud-Endpunkt ist erforderlich.",
"cloud-endpoint-hint": "Edge erfordert HTTP-Zugriff auf die Cloud (ThingsBoard CE / PE), um den Lizenzschlüssel zu überprüfen. Bitte geben Sie die Cloud-URL an, zu der Edge eine Verbindung herstellen kann.",
"description": "Beschreibung",
"details": "Details",
"events": "Ereignisse",

10
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1487,14 +1487,6 @@
"name": "Name",
"name-starts-with": "Edge name starts with",
"name-required": "Name is required.",
"edge-license-key": "Edge License Key",
"edge-license-key-required": "Edge License Key is required.",
"edge-license-key-max-length": "Edge License Key should be less than 31",
"edge-license-key-hint": "To obtain your license please navigate to the <a href='https://thingsboard.io/pricing/?active=thingsboard-edge' target='_blank'>pricing page</a> and select the best license option for your case.",
"cloud-endpoint": "Cloud Endpoint",
"cloud-endpoint-required": "Cloud Endpoint is required.",
"cloud-endpoint-max-length": "Cloud Endpoint should be less than 256",
"cloud-endpoint-hint": "Edge requires HTTP(s) access to Cloud (ThingsBoard CE/PE) to verify the license key. Please specify Cloud URL that Edge is able to connect to.",
"description": "Description",
"details": "Details",
"events": "Events",
@ -2300,8 +2292,6 @@
"isgateway": "Is Gateway",
"activity-time-from-gateway-device": "Activity time from gateway device",
"description": "Description",
"edge-license-key": "License Key",
"cloud-endpoint": "Cloud Endpoint",
"routing-key": "Edge key",
"secret": "Edge secret"
},

6
ui-ngx/src/assets/locale/locale.constant-es_ES.json

@ -1126,12 +1126,6 @@
"name": "Nombre",
"name-starts-with": "Edge name starts with",
"name-required": "Se requiere nombre",
"edge-license-key": "Edge Clave de licencia",
"edge-license-key-required": "Se requiere edge clave de licencia",
"edge-license-key-hint": "Para obtener su licencia, vaya a la <a href='https://thingsboard.io/pricing/?active=thingsboard-edge' target='_blank'> página de precios </a> y seleccione la mejor opción de licencia para su caso.",
"cloud-endpoint": "Punto final de la nube",
"cloud-endpoint-required": "Se requiere punto final de la nube",
"cloud-endpoint-hint": "Edge requiere acceso HTTP (s) a la nube (ThingsBoard CE / PE) para verificar la clave de licencia. Especifique la URL de la nube a la que Edge puede conectarse.",
"description": "Descripción",
"details": "Detalles",
"events": "Eventos",

6
ui-ngx/src/assets/locale/locale.constant-fr_FR.json

@ -758,12 +758,6 @@
"name": "Nom",
"name-starts-with": "Le nom du bord commence par",
"name-required": "Le nom de la bordure est requis",
"edge-license-key": "Edge Clé de licence",
"edge-license-key-required": "La edge clé de licence est requise",
"edge-license-key-hint": "Pour obtenir votre licence, accédez à la <a href='https://thingsboard.io/pricing/?active=thingsboard-edge' target='_blank'> page de tarification</a> and select the best license option for your case.",
"cloud-endpoint": "Clé de licence",
"cloud-endpoint-required": "La clé de licence est requise",
"cloud-endpoint-hint": "Edge nécessite un accès HTTP (s) au Cloud (ThingsBoard CE / PE) pour vérifier la clé de licence. Veuillez spécifier l'URL du cloud à laquelle Edge peut se connecter.",
"description": "Dispositifs",
"details": "Détails de l'entité",
"events": "Événements",

8
ui-ngx/src/assets/locale/locale.constant-tr_TR.json

@ -1404,12 +1404,6 @@
"name": "Name",
"name-starts-with": "Edge name starts with",
"name-required": "Name is required.",
"edge-license-key": "Edge License Key",
"edge-license-key-required": "Edge License Key is required.",
"edge-license-key-hint": "To obtain your license please navigate to the <a href='https://thingsboard.io/pricing/?active=thingsboard-edge' target='_blank'>pricing page</a> and select the best license option for your case.",
"cloud-endpoint": "Cloud Endpoint",
"cloud-endpoint-required": "Cloud Endpoint is required.",
"cloud-endpoint-hint": "Edge requires HTTP(s) access to Cloud (ThingsBoard CE/PE) to verify the license key. Please specify Cloud URL that Edge is able to connect to.",
"description": "Description",
"details": "Details",
"events": "Events",
@ -2183,8 +2177,6 @@
"isgateway": "Ağ Geçidi",
"activity-time-from-gateway-device": "Ağ geçidi cihazından etkinlik süresi",
"description": "Açıklama",
"edge-license-key": "Lisans anahtarı",
"cloud-endpoint": "Bulut Uç Noktası",
"routing-key": "Uç Anahtarı",
"secret": "Uç Secret"
},

Loading…
Cancel
Save