diff --git a/application/pom.xml b/application/pom.xml
index 33b21b3243..3693fe6dbe 100644
--- a/application/pom.xml
+++ b/application/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
application
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java
index c8fdcc4537..3c2db96b31 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/DeviceMsgConstructor.java
@@ -16,7 +16,8 @@
package org.thingsboard.server.service.edge.rpc.constructor;
import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.protobuf.ByteString;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device;
@@ -28,6 +29,7 @@ import org.thingsboard.server.gen.edge.v1.DeviceRpcCallMsg;
import org.thingsboard.server.gen.edge.v1.DeviceUpdateMsg;
import org.thingsboard.server.gen.edge.v1.RpcRequestMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
+import org.thingsboard.server.queue.util.DataDecodingEncodingService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import java.util.UUID;
@@ -36,7 +38,8 @@ import java.util.UUID;
@TbCoreComponent
public class DeviceMsgConstructor {
- protected static final ObjectMapper mapper = new ObjectMapper();
+ @Autowired
+ private DataDecodingEncodingService dataDecodingEncodingService;
public DeviceUpdateMsg constructDeviceUpdatedMsg(UpdateMsgType msgType, Device device, CustomerId customerId, String conflictName) {
DeviceUpdateMsg.Builder builder = DeviceUpdateMsg.newBuilder()
@@ -66,6 +69,9 @@ public class DeviceMsgConstructor {
if (conflictName != null) {
builder.setConflictName(conflictName);
}
+ if (device.getDeviceData() != null) {
+ builder.setDeviceDataBytes(ByteString.copyFrom(dataDecodingEncodingService.encode(device.getDeviceData())));
+ }
return builder.build();
}
diff --git a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java
index 3e728ef04a..6d0f66a884 100644
--- a/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java
+++ b/application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/DeviceEdgeProcessor.java
@@ -22,6 +22,7 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Customer;
@@ -29,6 +30,7 @@ import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.StringUtils;
+import org.thingsboard.server.common.data.device.data.DeviceData;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
@@ -59,9 +61,11 @@ import org.thingsboard.server.gen.edge.v1.DownlinkMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.queue.TbQueueCallback;
import org.thingsboard.server.queue.TbQueueMsgMetadata;
+import org.thingsboard.server.queue.util.DataDecodingEncodingService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.rpc.FromDeviceRpcResponseActorMsg;
+import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
@@ -70,6 +74,9 @@ import java.util.concurrent.locks.ReentrantLock;
@TbCoreComponent
public class DeviceEdgeProcessor extends BaseEdgeProcessor {
+ @Autowired
+ private DataDecodingEncodingService dataDecodingEncodingService;
+
private static final ReentrantLock deviceCreationLock = new ReentrantLock();
public ListenableFuture processDeviceFromEdge(TenantId tenantId, Edge edge, DeviceUpdateMsg deviceUpdateMsg) {
@@ -191,6 +198,11 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
deviceUpdateMsg.getDeviceProfileIdLSB()));
device.setDeviceProfileId(deviceProfileId);
}
+ Optional deviceDataOpt =
+ dataDecodingEncodingService.decode(deviceUpdateMsg.getDeviceDataBytes().toByteArray());
+ if (deviceDataOpt.isPresent()) {
+ device.setDeviceData(deviceDataOpt.get());
+ }
Device savedDevice = deviceService.saveDevice(device);
tbClusterService.onDeviceUpdated(savedDevice, device);
return saveEdgeEvent(tenantId, edge.getId(), EdgeEventType.DEVICE, EdgeEventActionType.CREDENTIALS_REQUEST, deviceId, null);
@@ -231,6 +243,11 @@ public class DeviceEdgeProcessor extends BaseEdgeProcessor {
deviceUpdateMsg.getDeviceProfileIdLSB()));
device.setDeviceProfileId(deviceProfileId);
}
+ Optional deviceDataOpt =
+ dataDecodingEncodingService.decode(deviceUpdateMsg.getDeviceDataBytes().toByteArray());
+ if (deviceDataOpt.isPresent()) {
+ device.setDeviceData(deviceDataOpt.get());
+ }
if (created) {
deviceValidator.validate(device, Device::getTenantId);
device.setId(deviceId);
diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml
index fb1cd746f3..9edd5d0ed5 100644
--- a/application/src/main/resources/thingsboard.yml
+++ b/application/src/main/resources/thingsboard.yml
@@ -260,7 +260,7 @@ sql:
stats_print_interval_ms: "${SQL_EVENTS_BATCH_STATS_PRINT_MS:10000}"
batch_threads: "${SQL_EVENTS_BATCH_THREADS:3}" # batch thread count have to be a prime number like 3 or 5 to gain perfect hash distribution
partition_size: "${SQL_EVENTS_REGULAR_PARTITION_SIZE_HOURS:168}" # Number of hours to partition the events. The current value corresponds to one week.
- debug_partition_size: "${SQL_EVENTS_REGULAR_PARTITION_SIZE_HOURS:1}" # Number of hours to partition the debug events. The current value corresponds to one hour.
+ debug_partition_size: "${SQL_EVENTS_DEBUG_PARTITION_SIZE_HOURS:1}" # Number of hours to partition the debug events. The current value corresponds to one hour.
edge_events:
batch_size: "${SQL_EDGE_EVENTS_BATCH_SIZE:1000}"
batch_max_delay: "${SQL_EDGE_EVENTS_BATCH_MAX_DELAY_MS:100}"
diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
index 462b40135a..09c40f263c 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AbstractWebTest.java
@@ -27,6 +27,7 @@ import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.hamcrest.Matcher;
+import org.hibernate.exception.ConstraintViolationException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
@@ -34,6 +35,7 @@ import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
+import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
@@ -67,6 +69,7 @@ import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadCo
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
@@ -74,20 +77,25 @@ import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.TimePageLink;
+import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.config.ThingsboardSecurityConfiguration;
+import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.service.mail.TestMailService;
import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRequest;
import org.thingsboard.server.service.security.auth.rest.LoginRequest;
import java.io.IOException;
+import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
@@ -656,7 +664,11 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
}
protected T readResponse(ResultActions result, TypeReference type) throws Exception {
- byte[] content = result.andReturn().getResponse().getContentAsByteArray();
+ return readResponse(result.andReturn(), type);
+ }
+
+ protected T readResponse(MvcResult result, TypeReference type) throws Exception {
+ byte[] content = result.getResponse().getContentAsByteArray();
return mapper.readerFor(type).readValue(content);
}
@@ -699,4 +711,49 @@ public abstract class AbstractWebTest extends AbstractInMemoryStorageTest {
return Futures.allAsList(futures);
}
+ protected void testEntityDaoWithRelationsOk(EntityId entityIdFrom, EntityId entityTo, String urlDelete) throws Exception {
+ createEntityRelation(entityIdFrom, entityTo, "TEST_TYPE");
+ assertThat(findRelationsByTo(entityTo)).hasSize(1);
+
+ doDelete(urlDelete).andExpect(status().isOk());
+
+ assertThat(findRelationsByTo(entityTo)).hasSize(0);
+ }
+
+ protected void testEntityDaoWithRelationsTransactionalException(Dao dao, EntityId entityIdFrom, EntityId entityTo,
+ String urlDelete) throws Exception {
+ entityDaoRemoveByIdWithException (dao);
+ createEntityRelation(entityIdFrom, entityTo, "TEST_TRANSACTIONAL_TYPE");
+ assertThat(findRelationsByTo(entityTo)).hasSize(1);
+
+ doDelete(urlDelete)
+ .andExpect(status().isInternalServerError());
+
+ assertThat(findRelationsByTo(entityTo)).hasSize(1);
+ }
+
+ protected void entityDaoRemoveByIdWithException (Dao dao) throws Exception {
+ BDDMockito.willThrow(new ConstraintViolationException("mock message", new SQLException(), "MOCK_CONSTRAINT"))
+ .given(dao).removeById(any(), any());
+ }
+
+ protected void afterTestEntityDaoRemoveByIdWithException (Dao dao) throws Exception {
+ BDDMockito.willCallRealMethod().given(dao).removeById(any(), any());
+ }
+
+ protected void createEntityRelation(EntityId entityIdFrom, EntityId entityIdTo, String typeRelation) throws Exception {
+ EntityRelation relation = new EntityRelation(entityIdFrom, entityIdTo, typeRelation);
+ doPost("/api/relation", relation);
+ }
+
+ protected List findRelationsByTo(EntityId entityId) throws Exception {
+ String url = String.format("/api/relations?toId=%s&toType=%s", entityId.getId(), entityId.getEntityType().name());
+ MvcResult mvcResult = doGet(url).andReturn();
+
+ switch (mvcResult.getResponse().getStatus()) {
+ case 200: return readResponse(mvcResult, new TypeReference<>() {});
+ case 404: return Collections.emptyList();
+ }
+ throw new AssertionError("Unexpected status " + mvcResult.getResponse().getStatus());
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java
index 14e260ab14..a2b8b908d5 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseAlarmControllerTest.java
@@ -23,6 +23,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityType;
@@ -31,7 +32,9 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.audit.ActionType;
+import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.page.PageData;
+import org.thingsboard.server.dao.alarm.AlarmDao;
import java.util.LinkedList;
import java.util.List;
@@ -46,6 +49,10 @@ public abstract class BaseAlarmControllerTest extends AbstractControllerTest {
protected Device customerDevice;
+
+ @SpyBean
+ private AlarmDao alarmDao;
+
@Before
public void setup() throws Exception {
loginTenantAdmin();
@@ -64,6 +71,9 @@ public abstract class BaseAlarmControllerTest extends AbstractControllerTest {
@After
public void teardown() throws Exception {
loginSysAdmin();
+
+ afterTestEntityDaoRemoveByIdWithException (alarmDao);
+
deleteDifferentTenant();
}
@@ -421,6 +431,21 @@ public abstract class BaseAlarmControllerTest extends AbstractControllerTest {
Assert.assertTrue("Created alarm doesn't match the found one!", equals);
}
+
+ @Test
+ public void testDeleteAlarmWithDeleteRelationsOk() throws Exception {
+ loginCustomerUser();
+ AlarmId alarmId = createAlarm("Alarm for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(customerDevice.getId(), alarmId, "/api/alarm/" + alarmId);
+ }
+
+ @Test
+ public void testDeleteAlarmExceptionWithRelationsTransactional() throws Exception {
+ loginCustomerUser();
+ AlarmId alarmId = createAlarm("Alarm for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(alarmDao, customerDevice.getId(), alarmId, "/api/alarm/" + alarmId);
+ }
+
private Alarm createAlarm(String type) throws Exception {
Alarm alarm = Alarm.builder()
.tenantId(tenantId)
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java
index 68b05ada27..4e9c01e4cc 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java
@@ -22,6 +22,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityView;
@@ -31,10 +32,12 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
+import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
+import org.thingsboard.server.dao.asset.AssetDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.service.stats.DefaultRuleEngineStatisticsService;
@@ -54,6 +57,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest {
private Tenant savedTenant;
private User tenantAdmin;
+ @SpyBean
+ private AssetDao assetDao;
+
@Before
public void beforeTest() throws Exception {
loginSysAdmin();
@@ -77,6 +83,8 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest {
public void afterTest() throws Exception {
loginSysAdmin();
+ afterTestEntityDaoRemoveByIdWithException (assetDao);
+
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
.andExpect(status().isOk());
}
@@ -905,4 +913,23 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest {
Assert.assertEquals(0, pageData.getData().size());
}
+
+ @Test
+ public void testDeleteAssetWithDeleteRelationsOk() throws Exception {
+ AssetId assetId = createAsset("Asset for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(savedTenant.getId(), assetId, "/api/asset/" + assetId);
+ }
+
+ @Test
+ public void testDeleteAssetExceptionWithRelationsTransactional() throws Exception {
+ AssetId assetId = createAsset("Asset for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(assetDao, savedTenant.getId(), assetId, "/api/asset/" + assetId);
+ }
+
+ private Asset createAsset(String name) {
+ Asset asset = new Asset();
+ asset.setName(name);
+ asset.setType("default");
+ return doPost("/api/asset", asset, Asset.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java
index 9ce4dc6025..d3cc1761c7 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseCustomerControllerTest.java
@@ -25,6 +25,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.thingsboard.common.util.ThingsBoardExecutors;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.StringUtils;
@@ -36,6 +37,7 @@ 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.security.Authority;
+import org.thingsboard.server.dao.customer.CustomerDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import java.util.ArrayList;
@@ -55,6 +57,9 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest
private Tenant savedTenant;
private User tenantAdmin;
+ @SpyBean
+ private CustomerDao customerDao;
+
@Before
public void beforeTest() throws Exception {
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(8, getClass()));
@@ -82,6 +87,8 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest
loginSysAdmin();
+ afterTestEntityDaoRemoveByIdWithException (customerDao);
+
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
.andExpect(status().isOk());
}
@@ -402,4 +409,22 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest
Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(0, pageData.getData().size());
}
+
+ @Test
+ public void testDeleteCustomerWithDeleteRelationsOk() throws Exception {
+ CustomerId customerId = createCustomer("Customer for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(savedTenant.getId(), customerId, "/api/customer/" + customerId);
+ }
+
+ @Test
+ public void testDeleteCustomerExceptionWithRelationsTransactional() throws Exception {
+ CustomerId customerId = createCustomer("Customer for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(customerDao, savedTenant.getId(), customerId, "/api/customer/" + customerId);
+ }
+
+ private Customer createCustomer(String title) {
+ Customer customer = new Customer();
+ customer.setTitle(title);
+ return doPost("/api/customer", customer, Customer.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java
index f5478845a9..50050c6306 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseDashboardControllerTest.java
@@ -22,6 +22,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DashboardInfo;
@@ -31,9 +32,11 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
+import org.thingsboard.server.dao.dashboard.DashboardDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import java.util.ArrayList;
@@ -50,6 +53,9 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest
private Tenant savedTenant;
private User tenantAdmin;
+ @SpyBean
+ private DashboardDao dashboardDao;
+
@Before
public void beforeTest() throws Exception {
loginSysAdmin();
@@ -73,41 +79,12 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest
public void afterTest() throws Exception {
loginSysAdmin();
+ afterTestEntityDaoRemoveByIdWithException (dashboardDao);
+
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
.andExpect(status().isOk());
}
- @Test
- public void testSaveDashboard() throws Exception {
- Dashboard dashboard = new Dashboard();
- dashboard.setTitle("My dashboard");
-
- Mockito.reset(tbClusterService, auditLogService);
-
- Dashboard savedDashboard = doPost("/api/dashboard", dashboard, Dashboard.class);
-
- testNotifyEntityOneTimeMsgToEdgeServiceNever(savedDashboard, savedDashboard.getId(), savedDashboard.getId(), savedTenant.getId(),
- tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.ADDED);
-
- Assert.assertNotNull(savedDashboard);
- Assert.assertNotNull(savedDashboard.getId());
- Assert.assertTrue(savedDashboard.getCreatedTime() > 0);
- Assert.assertEquals(savedTenant.getId(), savedDashboard.getTenantId());
- Assert.assertEquals(dashboard.getTitle(), savedDashboard.getTitle());
-
- savedDashboard.setTitle("My new dashboard");
-
- Mockito.reset(tbClusterService, auditLogService);
-
- doPost("/api/dashboard", savedDashboard, Dashboard.class);
-
- testNotifyEntityAllOneTime(savedDashboard, savedDashboard.getId(), savedDashboard.getId(), savedTenant.getId(),
- tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED);
-
- Dashboard foundDashboard = doGet("/api/dashboard/" + savedDashboard.getId().getId().toString(), Dashboard.class);
- Assert.assertEquals(foundDashboard.getTitle(), savedDashboard.getTitle());
- }
-
@Test
public void testSaveDashboardInfoWithViolationOfValidation() throws Exception {
Dashboard dashboard = new Dashboard();
@@ -495,4 +472,21 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest
Assert.assertEquals(0, pageData.getData().size());
}
+ @Test
+ public void testDeleteDashboardWithDeleteRelationsOk() throws Exception {
+ DashboardId dashboardId = createDashboard("Dashboard for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(savedTenant.getId(), dashboardId, "/api/dashboard/" + dashboardId);
+ }
+
+ @Test
+ public void testDeleteDashboardExceptionWithRelationsTransactional() throws Exception {
+ DashboardId dashboardId = createDashboard("Dashboard for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(dashboardDao, savedTenant.getId(), dashboardId, "/api/dashboard/" + dashboardId);
+ }
+
+ private Dashboard createDashboard(String title) {
+ Dashboard dashboard = new Dashboard();
+ dashboard.setTitle(title);
+ return doPost("/api/dashboard", dashboard, Dashboard.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java
index 8329b96781..abe8b78918 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java
@@ -50,6 +50,7 @@ import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
+import org.thingsboard.server.dao.device.DeviceDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException;
import org.thingsboard.server.dao.model.ModelConstants;
@@ -82,6 +83,10 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest {
@SpyBean
private GatewayNotificationsService gatewayNotificationsService;
+ @SpyBean
+ private DeviceDao deviceDao;
+
+
@Before
public void beforeTest() throws Exception {
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(8, getClass()));
@@ -109,6 +114,8 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest {
loginSysAdmin();
+ afterTestEntityDaoRemoveByIdWithException (deviceDao);
+
doDelete("/api/tenant/" + savedTenant.getId().getId())
.andExpect(status().isOk());
}
@@ -1203,4 +1210,23 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest {
protected void testNotificationDeleteGatewayNever() {
Mockito.verify(gatewayNotificationsService, never()).onDeviceDeleted(Mockito.any(Device.class));
}
+
+ @Test
+ public void testDeleteDashboardWithDeleteRelationsOk() throws Exception {
+ DeviceId deviceId = createDevice("Device for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(savedTenant.getId(), deviceId, "/api/device/" + deviceId);
+ }
+
+ @Test
+ public void testDeleteDeviceExceptionWithRelationsTransactional() throws Exception {
+ DeviceId deviceId = createDevice("Device for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(deviceDao, savedTenant.getId(), deviceId, "/api/device/" + deviceId);
+ }
+
+ private Device createDevice(String name) {
+ Device device = new Device();
+ device.setName(name);
+ device.setType("default");
+ return doPost("/api/device", device, Device.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java
index c69c1ac45a..0c042d5006 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceProfileControllerTest.java
@@ -27,6 +27,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.Device;
@@ -46,10 +47,12 @@ import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadCon
import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.TransportPayloadTypeConfiguration;
+import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.security.Authority;
+import org.thingsboard.server.dao.device.DeviceProfileDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import java.util.ArrayList;
@@ -74,6 +77,9 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController
private Tenant savedTenant;
private User tenantAdmin;
+ @SpyBean
+ private DeviceProfileDao deviceProfileDao;
+
@Before
public void beforeTest() throws Exception {
loginSysAdmin();
@@ -97,6 +103,8 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController
public void afterTest() throws Exception {
loginSysAdmin();
+ afterTestEntityDaoRemoveByIdWithException (deviceProfileDao);
+
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
.andExpect(status().isOk());
}
@@ -1125,4 +1133,20 @@ public abstract class BaseDeviceProfileControllerTest extends AbstractController
return JsonFormat.printer().includingDefaultValueFields().print(dynamicMessage);
}
+ @Test
+ public void testDeleteDeviceProfileWithDeleteRelationsOk() throws Exception {
+ DeviceProfileId deviceProfileId = savedDeviceProfile("DeviceProfile for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(savedTenant.getId(), deviceProfileId, "/api/deviceProfile/" + deviceProfileId);
+ }
+
+ @Test
+ public void testDeleteDeviceProfileExceptionWithRelationsTransactional() throws Exception {
+ DeviceProfileId deviceProfileId = savedDeviceProfile("DeviceProfile for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(deviceProfileDao, savedTenant.getId(), deviceProfileId, "/api/deviceProfile/" + deviceProfileId);
+ }
+
+ private DeviceProfile savedDeviceProfile(String name) {
+ DeviceProfile deviceProfile = createDeviceProfile(name);
+ return doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java
index da1f7d935e..c3d747cb35 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseEdgeControllerTest.java
@@ -22,6 +22,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.TestPropertySource;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
@@ -33,10 +34,12 @@ import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.EdgeId;
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.security.Authority;
+import org.thingsboard.server.dao.edge.EdgeDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.edge.imitator.EdgeImitator;
@@ -72,6 +75,9 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
private TenantId tenantId;
private User tenantAdmin;
+ @SpyBean
+ private EdgeDao edgeDao;
+
@Before
public void beforeTest() throws Exception {
loginSysAdmin();
@@ -96,6 +102,8 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
public void afterTest() throws Exception {
loginSysAdmin();
+ afterTestEntityDaoRemoveByIdWithException (edgeDao);
+
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
.andExpect(status().isOk());
}
@@ -837,4 +845,20 @@ public abstract class BaseEdgeControllerTest extends AbstractControllerTest {
.andExpect(status().isOk());
}
+ @Test
+ public void testDeleteEdgeWithDeleteRelationsOk() throws Exception {
+ EdgeId edgeId = savedEdge("Edge for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(savedTenant.getId(), edgeId, "/api/edge/" + edgeId);
+ }
+
+ @Test
+ public void testDeleteEdgeExceptionWithRelationsTransactional() throws Exception {
+ EdgeId edgeId = savedEdge("Edge for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(edgeDao, savedTenant.getId(), edgeId, "/api/edge/" + edgeId);
+ }
+
+ private Edge savedEdge(String name) {
+ Edge edge = constructEdge(name, "default");
+ return doPost("/api/edge", edge, Edge.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java
index 950024a87a..5bddb9b3a7 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java
@@ -32,6 +32,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.ResultActions;
import org.thingsboard.common.util.ThingsBoardExecutors;
@@ -45,6 +46,7 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.id.CustomerId;
+import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.objects.AttributesEntityView;
import org.thingsboard.server.common.data.objects.TelemetryEntityView;
import org.thingsboard.server.common.data.page.PageData;
@@ -54,6 +56,7 @@ import org.thingsboard.server.common.data.query.EntityKey;
import org.thingsboard.server.common.data.query.EntityKeyType;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.security.DeviceCredentials;
+import org.thingsboard.server.dao.entityview.EntityViewDao;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.model.ModelConstants;
@@ -93,6 +96,9 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
List> deleteFutures = new ArrayList<>();
ListeningExecutorService executor;
+ @SpyBean
+ private EntityViewDao entityViewDao;
+
@Before
public void beforeTest() throws Exception {
executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(8, getClass()));
@@ -114,6 +120,9 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
@After
public void afterTest() throws Exception {
+
+ afterTestEntityDaoRemoveByIdWithException (entityViewDao);
+
executor.shutdownNow();
}
@@ -786,4 +795,16 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes
Assert.assertEquals(0, pageData.getData().size());
}
+
+ @Test
+ public void testDeleteEntityViewWithDeleteRelationsOk() throws Exception {
+ EntityViewId entityViewId = getNewSavedEntityView("EntityView for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(tenantId, entityViewId, "/api/entityView/" + entityViewId);
+ }
+
+ @Test
+ public void testDeleteEntityViewExceptionWithRelationsTransactional() throws Exception {
+ EntityViewId entityViewId = getNewSavedEntityView("EntityView for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(entityViewDao, tenantId, entityViewId, "/api/entityView/" + entityViewId);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java
index 6dabc4023d..bec15dac8c 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseRuleChainControllerTest.java
@@ -21,17 +21,20 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
+import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.exception.DataValidationException;
+import org.thingsboard.server.dao.rule.RuleChainDao;
import java.util.ArrayList;
import java.util.Collections;
@@ -47,6 +50,9 @@ public abstract class BaseRuleChainControllerTest extends AbstractControllerTest
private Tenant savedTenant;
private User tenantAdmin;
+ @SpyBean
+ private RuleChainDao ruleChainDao;
+
@Before
public void beforeTest() throws Exception {
loginSysAdmin();
@@ -70,6 +76,8 @@ public abstract class BaseRuleChainControllerTest extends AbstractControllerTest
public void afterTest() throws Exception {
loginSysAdmin();
+ afterTestEntityDaoRemoveByIdWithException(ruleChainDao);
+
doDelete("/api/tenant/" + savedTenant.getId().getId().toString())
.andExpect(status().isOk());
}
@@ -223,4 +231,21 @@ public abstract class BaseRuleChainControllerTest extends AbstractControllerTest
Assert.assertEquals(1, pageData.getTotalElements());
}
+ @Test
+ public void testDeleteRuleChainWithDeleteRelationsOk() throws Exception {
+ RuleChainId ruleChainId = createRuleChain("RuleChain for Test WithRelationsOk").getId();
+ testEntityDaoWithRelationsOk(savedTenant.getId(), ruleChainId, "/api/ruleChain/" + ruleChainId);
+ }
+
+ @Test
+ public void testDeleteRuleChainExceptionWithRelationsTransactional() throws Exception {
+ RuleChainId ruleChainId = createRuleChain("RuleChain for Test WithRelations Transactional Exception").getId();
+ testEntityDaoWithRelationsTransactionalException(ruleChainDao, savedTenant.getId(), ruleChainId, "/api/ruleChain/" + ruleChainId);
+ }
+
+ private RuleChain createRuleChain(String name) {
+ RuleChain ruleChain = new RuleChain();
+ ruleChain.setName(name);
+ return doPost("/api/ruleChain", ruleChain, RuleChain.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java
index 75a2ae83eb..141896ed4b 100644
--- a/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/BaseUserControllerTest.java
@@ -18,9 +18,11 @@ package org.thingsboard.server.controller;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.http.HttpHeaders;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.StringUtils;
@@ -29,10 +31,12 @@ import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.exception.DataValidationException;
+import org.thingsboard.server.dao.user.UserDao;
import org.thingsboard.server.service.mail.TestMailService;
import java.util.ArrayList;
@@ -53,6 +57,16 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest {
private CustomerId customerNUULId = (CustomerId) createEntityId_NULL_UUID(new Customer());
+ @SpyBean
+ private UserDao userDao;
+
+ @After
+ public void afterTest() throws Exception {
+ loginSysAdmin();
+
+ afterTestEntityDaoRemoveByIdWithException(userDao);
+ }
+
@Test
public void testSaveUser() throws Exception {
loginSysAdmin();
@@ -688,4 +702,29 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest {
doDelete("/api/customer/" + customerId.getId().toString())
.andExpect(status().isOk());
}
+
+
+ @Test
+ public void testDeleteUserWithDeleteRelationsOk() throws Exception {
+ UserId userId = createUser().getId();
+ testEntityDaoWithRelationsOk(tenantId, userId, "/api/user/" + userId);
+ }
+
+ @Test
+ public void testDeleteUserExceptionWithRelationsTransactional() throws Exception {
+ UserId userId = createUser().getId();
+ testEntityDaoWithRelationsTransactionalException(userDao, tenantId, userId, "/api/user/" + userId);
+ }
+
+ private User createUser() throws Exception {
+ loginSysAdmin();
+ String email = "tenant2@thingsboard.org";
+ User user = new User();
+ user.setAuthority(Authority.TENANT_ADMIN);
+ user.setTenantId(tenantId);
+ user.setEmail(email);
+ user.setFirstName("Joe");
+ user.setLastName("Downs");
+ return doPost("/api/user", user, User.class);
+ }
}
diff --git a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java
index 6246492d25..dcd354ace5 100644
--- a/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java
+++ b/application/src/test/java/org/thingsboard/server/edge/BaseEdgeTest.java
@@ -43,6 +43,7 @@ import org.thingsboard.server.common.data.Dashboard;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceProfile;
+import org.thingsboard.server.common.data.DeviceTransportType;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
import org.thingsboard.server.common.data.OtaPackageInfo;
@@ -56,17 +57,32 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.asset.Asset;
+import org.thingsboard.server.common.data.device.data.DefaultDeviceConfiguration;
+import org.thingsboard.server.common.data.device.data.DeviceData;
+import org.thingsboard.server.common.data.device.data.MqttDeviceTransportConfiguration;
+import org.thingsboard.server.common.data.device.data.PowerMode;
+import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration;
import org.thingsboard.server.common.data.device.profile.AlarmCondition;
import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter;
import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey;
import org.thingsboard.server.common.data.device.profile.AlarmConditionKeyType;
import org.thingsboard.server.common.data.device.profile.AlarmRule;
import org.thingsboard.server.common.data.device.profile.AllowCreateNewDevicesDeviceProfileProvisionConfiguration;
+import org.thingsboard.server.common.data.device.profile.CoapDeviceProfileTransportConfiguration;
+import org.thingsboard.server.common.data.device.profile.DefaultCoapDeviceTypeConfiguration;
import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
+import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration;
import org.thingsboard.server.common.data.device.profile.JsonTransportPayloadConfiguration;
-import org.thingsboard.server.common.data.device.profile.MqttDeviceProfileTransportConfiguration;
+import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration;
+import org.thingsboard.server.common.data.device.profile.ProtoTransportPayloadConfiguration;
import org.thingsboard.server.common.data.device.profile.SimpleAlarmConditionSpec;
+import org.thingsboard.server.common.data.device.profile.SnmpDeviceProfileTransportConfiguration;
+import org.thingsboard.server.common.data.device.profile.lwm2m.OtherConfiguration;
+import org.thingsboard.server.common.data.device.profile.lwm2m.TelemetryMappingConfiguration;
+import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.AbstractLwM2MBootstrapServerCredential;
+import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.LwM2MBootstrapServerCredential;
+import org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap.NoSecLwM2MBootstrapServerCredential;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
@@ -77,6 +93,7 @@ import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.kv.DataType;
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
import org.thingsboard.server.common.data.ota.OtaPackageType;
import org.thingsboard.server.common.data.page.PageData;
@@ -99,6 +116,9 @@ import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.data.security.DeviceCredentialsType;
import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration;
+import org.thingsboard.server.common.data.transport.snmp.SnmpMapping;
+import org.thingsboard.server.common.data.transport.snmp.config.SnmpCommunicationConfig;
+import org.thingsboard.server.common.data.transport.snmp.config.impl.TelemetryQueryingSnmpCommunicationConfig;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.common.msg.queue.ServiceType;
@@ -139,9 +159,13 @@ 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.queue.util.DataDecodingEncodingService;
+import org.thingsboard.server.transport.AbstractTransportIntegrationTest;
+import org.thingsboard.server.transport.lwm2m.AbstractLwM2MIntegrationTest;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -172,6 +196,9 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
@Autowired
private EdgeEventService edgeEventService;
+ @Autowired
+ private DataDecodingEncodingService dataDecodingEncodingService;
+
@Autowired
private TbClusterService clusterService;
@@ -246,10 +273,8 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
private void installation() throws Exception {
edge = doPost("/api/edge", constructEdge("Test Edge", "test"), Edge.class);
- MqttDeviceProfileTransportConfiguration transportConfiguration = new MqttDeviceProfileTransportConfiguration();
- transportConfiguration.setTransportPayloadTypeConfiguration(new JsonTransportPayloadConfiguration());
-
- thermostatDeviceProfile = this.createDeviceProfile(THERMOSTAT_DEVICE_PROFILE_NAME, transportConfiguration);
+ thermostatDeviceProfile = this.createDeviceProfile(THERMOSTAT_DEVICE_PROFILE_NAME,
+ createMqttDeviceProfileTransportConfiguration(new JsonTransportPayloadConfiguration(), false));
extendDeviceProfileData(thermostatDeviceProfile);
thermostatDeviceProfile = doPost("/api/deviceProfile", thermostatDeviceProfile, DeviceProfile.class);
@@ -439,6 +464,226 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(deviceProfileUpdateMsg.getIdLSB(), deviceProfile.getUuidId().getLeastSignificantBits());
}
+ @Test
+ public void testDeviceProfiles_snmp() throws Exception {
+ DeviceProfile deviceProfile = createDeviceProfileAndDoBasicAssert("SNMP", createSnmpDeviceProfileTransportConfiguration());
+
+ AbstractMessage latestMessage = edgeImitator.getLatestMessage();
+ Assert.assertTrue(latestMessage instanceof DeviceProfileUpdateMsg);
+ DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) latestMessage;
+ Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceProfileUpdateMsg.getMsgType());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdMSB(), deviceProfile.getUuidId().getMostSignificantBits());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdLSB(), deviceProfile.getUuidId().getLeastSignificantBits());
+ Assert.assertEquals(DeviceTransportType.SNMP.name(), deviceProfileUpdateMsg.getTransportType());
+
+ Optional deviceProfileDataOpt =
+ dataDecodingEncodingService.decode(deviceProfileUpdateMsg.getProfileDataBytes().toByteArray());
+
+ Assert.assertTrue(deviceProfileDataOpt.isPresent());
+ DeviceProfileData deviceProfileData = deviceProfileDataOpt.get();
+
+ Assert.assertTrue(deviceProfileData.getTransportConfiguration() instanceof SnmpDeviceProfileTransportConfiguration);
+ SnmpDeviceProfileTransportConfiguration transportConfiguration =
+ (SnmpDeviceProfileTransportConfiguration) deviceProfileData.getTransportConfiguration();
+ Assert.assertEquals(Integer.valueOf(1000), transportConfiguration.getTimeoutMs());
+ Assert.assertEquals(Integer.valueOf(3), transportConfiguration.getRetries());
+
+ Assert.assertFalse(transportConfiguration.getCommunicationConfigs().isEmpty());
+ SnmpCommunicationConfig communicationConfig = transportConfiguration.getCommunicationConfigs().get(0);
+ Assert.assertTrue(communicationConfig instanceof TelemetryQueryingSnmpCommunicationConfig);
+ TelemetryQueryingSnmpCommunicationConfig snmpCommunicationConfig =
+ (TelemetryQueryingSnmpCommunicationConfig) communicationConfig;
+
+ Assert.assertEquals(Long.valueOf(500L), snmpCommunicationConfig.getQueryingFrequencyMs());
+ Assert.assertFalse(snmpCommunicationConfig.getMappings().isEmpty());
+
+ SnmpMapping snmpMapping = snmpCommunicationConfig.getMappings().get(0);
+ Assert.assertEquals("temperature", snmpMapping.getKey());
+ Assert.assertEquals("1.3.3.5.6.7.8.9.1", snmpMapping.getOid());
+ Assert.assertEquals(DataType.DOUBLE, snmpMapping.getDataType());
+
+ removeDeviceProfileAndDoBasicAssert(deviceProfile);
+ }
+
+ @Test
+ public void testDeviceProfiles_lwm2m() throws Exception {
+ DeviceProfile deviceProfile = createDeviceProfileAndDoBasicAssert("LWM2M", createLwm2mDeviceProfileTransportConfiguration());
+
+ AbstractMessage latestMessage = edgeImitator.getLatestMessage();
+ Assert.assertTrue(latestMessage instanceof DeviceProfileUpdateMsg);
+ DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) latestMessage;
+ Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceProfileUpdateMsg.getMsgType());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdMSB(), deviceProfile.getUuidId().getMostSignificantBits());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdLSB(), deviceProfile.getUuidId().getLeastSignificantBits());
+ Assert.assertEquals(DeviceTransportType.LWM2M.name(), deviceProfileUpdateMsg.getTransportType());
+
+ Optional deviceProfileDataOpt =
+ dataDecodingEncodingService.decode(deviceProfileUpdateMsg.getProfileDataBytes().toByteArray());
+
+ Assert.assertTrue(deviceProfileDataOpt.isPresent());
+ DeviceProfileData deviceProfileData = deviceProfileDataOpt.get();
+
+ Assert.assertTrue(deviceProfileData.getTransportConfiguration() instanceof Lwm2mDeviceProfileTransportConfiguration);
+ Lwm2mDeviceProfileTransportConfiguration transportConfiguration =
+ (Lwm2mDeviceProfileTransportConfiguration) deviceProfileData.getTransportConfiguration();
+
+ OtherConfiguration clientLwM2mSettings = transportConfiguration.getClientLwM2mSettings();
+ Assert.assertEquals(PowerMode.DRX, clientLwM2mSettings.getPowerMode());
+ Assert.assertEquals(Integer.valueOf(1), clientLwM2mSettings.getFwUpdateStrategy());
+ Assert.assertEquals(Integer.valueOf(1), clientLwM2mSettings.getSwUpdateStrategy());
+ Assert.assertEquals(Integer.valueOf(1), clientLwM2mSettings.getClientOnlyObserveAfterConnect());
+
+ Assert.assertTrue(transportConfiguration.isBootstrapServerUpdateEnable());
+
+ Assert.assertFalse(transportConfiguration.getBootstrap().isEmpty());
+ LwM2MBootstrapServerCredential lwM2MBootstrapServerCredential = transportConfiguration.getBootstrap().get(0);
+ Assert.assertTrue(lwM2MBootstrapServerCredential instanceof NoSecLwM2MBootstrapServerCredential);
+ NoSecLwM2MBootstrapServerCredential noSecLwM2MBootstrapServerCredential = (NoSecLwM2MBootstrapServerCredential) lwM2MBootstrapServerCredential;
+
+ Assert.assertEquals("PUBLIC_KEY", noSecLwM2MBootstrapServerCredential.getServerPublicKey());
+ Assert.assertEquals(Integer.valueOf(123), noSecLwM2MBootstrapServerCredential.getShortServerId());
+ Assert.assertTrue(noSecLwM2MBootstrapServerCredential.isBootstrapServerIs());
+ Assert.assertEquals("localhost", noSecLwM2MBootstrapServerCredential.getHost());
+ Assert.assertEquals(Integer.valueOf(5687), noSecLwM2MBootstrapServerCredential.getPort());
+
+ TelemetryMappingConfiguration observeAttr = transportConfiguration.getObserveAttr();
+ Assert.assertEquals("batteryLevel", observeAttr.getKeyName().get("/3_1.0/0/9"));
+ Assert.assertTrue(observeAttr.getObserve().isEmpty());
+ Assert.assertTrue(observeAttr.getAttribute().isEmpty());
+ Assert.assertFalse(observeAttr.getTelemetry().isEmpty());
+ Assert.assertTrue(observeAttr.getTelemetry().contains("/3_1.0/0/9"));
+ Assert.assertTrue(observeAttr.getAttributeLwm2m().isEmpty());
+
+ removeDeviceProfileAndDoBasicAssert(deviceProfile);
+ }
+
+ @Test
+ public void testDeviceProfiles_coap() throws Exception {
+ DeviceProfile deviceProfile = createDeviceProfileAndDoBasicAssert("COAP", createCoapDeviceProfileTransportConfiguration());
+
+ AbstractMessage latestMessage = edgeImitator.getLatestMessage();
+ Assert.assertTrue(latestMessage instanceof DeviceProfileUpdateMsg);
+ DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) latestMessage;
+ Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, deviceProfileUpdateMsg.getMsgType());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdMSB(), deviceProfile.getUuidId().getMostSignificantBits());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdLSB(), deviceProfile.getUuidId().getLeastSignificantBits());
+ Assert.assertEquals(DeviceTransportType.COAP.name(), deviceProfileUpdateMsg.getTransportType());
+
+ Optional deviceProfileDataOpt =
+ dataDecodingEncodingService.decode(deviceProfileUpdateMsg.getProfileDataBytes().toByteArray());
+
+ Assert.assertTrue(deviceProfileDataOpt.isPresent());
+ DeviceProfileData deviceProfileData = deviceProfileDataOpt.get();
+
+ Assert.assertTrue(deviceProfileData.getTransportConfiguration() instanceof CoapDeviceProfileTransportConfiguration);
+ CoapDeviceProfileTransportConfiguration transportConfiguration =
+ (CoapDeviceProfileTransportConfiguration) deviceProfileData.getTransportConfiguration();
+
+ PowerSavingConfiguration clientSettings = transportConfiguration.getClientSettings();
+
+ Assert.assertEquals(PowerMode.DRX, clientSettings.getPowerMode());
+ Assert.assertEquals(Long.valueOf(1L), clientSettings.getEdrxCycle());
+ Assert.assertEquals(Long.valueOf(1L), clientSettings.getPsmActivityTimer());
+ Assert.assertEquals(Long.valueOf(1L), clientSettings.getPagingTransmissionWindow());
+
+ Assert.assertTrue(transportConfiguration.getCoapDeviceTypeConfiguration() instanceof DefaultCoapDeviceTypeConfiguration);
+ DefaultCoapDeviceTypeConfiguration coapDeviceTypeConfiguration =
+ (DefaultCoapDeviceTypeConfiguration) transportConfiguration.getCoapDeviceTypeConfiguration();
+
+ Assert.assertTrue(coapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration() instanceof ProtoTransportPayloadConfiguration);
+
+ ProtoTransportPayloadConfiguration protoTransportPayloadConfiguration =
+ (ProtoTransportPayloadConfiguration) coapDeviceTypeConfiguration.getTransportPayloadTypeConfiguration();
+
+ Assert.assertEquals(AbstractTransportIntegrationTest.DEVICE_TELEMETRY_PROTO_SCHEMA, protoTransportPayloadConfiguration.getDeviceTelemetryProtoSchema());
+ Assert.assertEquals(AbstractTransportIntegrationTest.DEVICE_ATTRIBUTES_PROTO_SCHEMA, protoTransportPayloadConfiguration.getDeviceAttributesProtoSchema());
+ Assert.assertEquals(AbstractTransportIntegrationTest.DEVICE_RPC_RESPONSE_PROTO_SCHEMA, protoTransportPayloadConfiguration.getDeviceRpcResponseProtoSchema());
+ Assert.assertEquals(AbstractTransportIntegrationTest.DEVICE_RPC_REQUEST_PROTO_SCHEMA, protoTransportPayloadConfiguration.getDeviceRpcRequestProtoSchema());
+
+ removeDeviceProfileAndDoBasicAssert(deviceProfile);
+ }
+
+ private DeviceProfile createDeviceProfileAndDoBasicAssert(String deviceProfileName, DeviceProfileTransportConfiguration deviceProfileTransportConfiguration) throws Exception {
+ DeviceProfile deviceProfile = this.createDeviceProfile(deviceProfileName, deviceProfileTransportConfiguration);
+ extendDeviceProfileData(deviceProfile);
+ edgeImitator.expectMessageAmount(1);
+ deviceProfile = doPost("/api/deviceProfile", deviceProfile, DeviceProfile.class);
+ Assert.assertTrue(edgeImitator.waitForMessages());
+ return deviceProfile;
+ }
+
+ private void removeDeviceProfileAndDoBasicAssert(DeviceProfile deviceProfile) throws Exception {
+ edgeImitator.expectMessageAmount(1);
+ doDelete("/api/deviceProfile/" + deviceProfile.getUuidId())
+ .andExpect(status().isOk());
+ Assert.assertTrue(edgeImitator.waitForMessages());
+ AbstractMessage latestMessage = edgeImitator.getLatestMessage();
+ Assert.assertTrue(latestMessage instanceof DeviceProfileUpdateMsg);
+ DeviceProfileUpdateMsg deviceProfileUpdateMsg = (DeviceProfileUpdateMsg) latestMessage;
+ Assert.assertEquals(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE, deviceProfileUpdateMsg.getMsgType());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdMSB(), deviceProfile.getUuidId().getMostSignificantBits());
+ Assert.assertEquals(deviceProfileUpdateMsg.getIdLSB(), deviceProfile.getUuidId().getLeastSignificantBits());
+ }
+
+ private SnmpDeviceProfileTransportConfiguration createSnmpDeviceProfileTransportConfiguration() {
+ SnmpDeviceProfileTransportConfiguration transportConfiguration = new SnmpDeviceProfileTransportConfiguration();
+ List communicationConfigs = new ArrayList<>();
+ TelemetryQueryingSnmpCommunicationConfig communicationConfig = new TelemetryQueryingSnmpCommunicationConfig();
+ communicationConfig.setQueryingFrequencyMs(500L);
+ List mappings = new ArrayList<>();
+ mappings.add(new SnmpMapping("1.3.3.5.6.7.8.9.1", "temperature", DataType.DOUBLE));
+ communicationConfig.setMappings(mappings);
+ communicationConfigs.add(communicationConfig);
+ transportConfiguration.setCommunicationConfigs(communicationConfigs);
+ transportConfiguration.setTimeoutMs(1000);
+ transportConfiguration.setRetries(3);
+ return transportConfiguration;
+ }
+
+ private Lwm2mDeviceProfileTransportConfiguration createLwm2mDeviceProfileTransportConfiguration() {
+ Lwm2mDeviceProfileTransportConfiguration transportConfiguration = new Lwm2mDeviceProfileTransportConfiguration();
+
+ OtherConfiguration clientLwM2mSettings = JacksonUtil.fromString(AbstractLwM2MIntegrationTest.CLIENT_LWM2M_SETTINGS, OtherConfiguration.class);
+ transportConfiguration.setClientLwM2mSettings(clientLwM2mSettings);
+
+ transportConfiguration.setBootstrapServerUpdateEnable(true);
+
+ TelemetryMappingConfiguration observeAttrConfiguration =
+ JacksonUtil.fromString(AbstractLwM2MIntegrationTest.OBSERVE_ATTRIBUTES_WITH_PARAMS, TelemetryMappingConfiguration.class);
+ transportConfiguration.setObserveAttr(observeAttrConfiguration);
+
+ List bootstrap = new ArrayList<>();
+ AbstractLwM2MBootstrapServerCredential bootstrapServerCredential = new NoSecLwM2MBootstrapServerCredential();
+ bootstrapServerCredential.setServerPublicKey("PUBLIC_KEY");
+ bootstrapServerCredential.setShortServerId(123);
+ bootstrapServerCredential.setBootstrapServerIs(true);
+ bootstrapServerCredential.setHost("localhost");
+ bootstrapServerCredential.setPort(5687);
+ bootstrap.add(bootstrapServerCredential);
+ transportConfiguration.setBootstrap(bootstrap);
+
+ return transportConfiguration;
+ }
+
+ private CoapDeviceProfileTransportConfiguration createCoapDeviceProfileTransportConfiguration() {
+ CoapDeviceProfileTransportConfiguration transportConfiguration = new CoapDeviceProfileTransportConfiguration();
+ PowerSavingConfiguration clientSettings = new PowerSavingConfiguration();
+ clientSettings.setPowerMode(PowerMode.DRX);
+ clientSettings.setEdrxCycle(1L);
+ clientSettings.setPsmActivityTimer(1L);
+ clientSettings.setPagingTransmissionWindow(1L);
+ transportConfiguration.setClientSettings(clientSettings);
+ DefaultCoapDeviceTypeConfiguration coapDeviceTypeConfiguration = new DefaultCoapDeviceTypeConfiguration();
+ ProtoTransportPayloadConfiguration transportPayloadTypeConfiguration = new ProtoTransportPayloadConfiguration();
+ transportPayloadTypeConfiguration.setDeviceTelemetryProtoSchema(AbstractTransportIntegrationTest.DEVICE_TELEMETRY_PROTO_SCHEMA);
+ transportPayloadTypeConfiguration.setDeviceAttributesProtoSchema(AbstractTransportIntegrationTest.DEVICE_ATTRIBUTES_PROTO_SCHEMA);
+ transportPayloadTypeConfiguration.setDeviceRpcResponseProtoSchema(AbstractTransportIntegrationTest.DEVICE_RPC_RESPONSE_PROTO_SCHEMA);
+ transportPayloadTypeConfiguration.setDeviceRpcRequestProtoSchema(AbstractTransportIntegrationTest.DEVICE_RPC_REQUEST_PROTO_SCHEMA);
+ coapDeviceTypeConfiguration.setTransportPayloadTypeConfiguration(transportPayloadTypeConfiguration);
+ transportConfiguration.setCoapDeviceTypeConfiguration(coapDeviceTypeConfiguration);
+ return transportConfiguration;
+ }
+
@Test
public void testDevices() throws Exception {
// 1
@@ -1911,6 +2156,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Device savedDevice = saveDevice(StringUtils.randomAlphanumeric(15), thermostatDeviceProfile.getName());
savedDevice.setFirmwareId(firmwareOtaPackageInfo.getId());
+
+ DeviceData deviceData = new DeviceData();
+ deviceData.setConfiguration(new DefaultDeviceConfiguration());
+ MqttDeviceTransportConfiguration transportConfiguration = new MqttDeviceTransportConfiguration();
+ transportConfiguration.getProperties().put("topic", "tb_rule_engine.thermostat");
+ deviceData.setTransportConfiguration(transportConfiguration);
+ savedDevice.setDeviceData(deviceData);
+
savedDevice = doPost("/api/device", savedDevice, Device.class);
// wait until device UPDATED event is sent to edge notification service
@@ -1930,6 +2183,14 @@ abstract public class BaseEdgeTest extends AbstractControllerTest {
Assert.assertEquals(deviceUpdateMsg.getType(), savedDevice.getType());
Assert.assertEquals(firmwareOtaPackageInfo.getUuidId().getMostSignificantBits(), deviceUpdateMsg.getFirmwareIdMSB());
Assert.assertEquals(firmwareOtaPackageInfo.getUuidId().getLeastSignificantBits(), deviceUpdateMsg.getFirmwareIdLSB());
+ Optional deviceDataOpt =
+ dataDecodingEncodingService.decode(deviceUpdateMsg.getDeviceDataBytes().toByteArray());
+ Assert.assertTrue(deviceDataOpt.isPresent());
+ deviceData = deviceDataOpt.get();
+ Assert.assertTrue(deviceData.getTransportConfiguration() instanceof MqttDeviceTransportConfiguration);
+ MqttDeviceTransportConfiguration mqttDeviceTransportConfiguration =
+ (MqttDeviceTransportConfiguration) deviceData.getTransportConfiguration();
+ Assert.assertEquals("tb_rule_engine.thermostat", mqttDeviceTransportConfiguration.getProperties().get("topic"));
return savedDevice;
}
diff --git a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java
index 09acd96d47..bdda6d52ed 100644
--- a/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java
+++ b/application/src/test/java/org/thingsboard/server/transport/AbstractTransportIntegrationTest.java
@@ -33,7 +33,7 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle
protected static final AtomicInteger atomicInteger = new AtomicInteger(2);
- protected static final String DEVICE_TELEMETRY_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
+ public static final String DEVICE_TELEMETRY_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
"\n" +
"package test;\n" +
"\n" +
@@ -54,7 +54,7 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle
" }\n" +
"}";
- protected static final String DEVICE_ATTRIBUTES_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
+ public static final String DEVICE_ATTRIBUTES_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
"\n" +
"package test;\n" +
"\n" +
@@ -75,14 +75,14 @@ public abstract class AbstractTransportIntegrationTest extends AbstractControlle
" }\n" +
"}";
- protected static final String DEVICE_RPC_RESPONSE_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
+ public static final String DEVICE_RPC_RESPONSE_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
"package rpc;\n" +
"\n" +
"message RpcResponseMsg {\n" +
" optional string payload = 1;\n" +
"}";
- protected static final String DEVICE_RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
+ public static final String DEVICE_RPC_REQUEST_PROTO_SCHEMA = "syntax =\"proto3\";\n" +
"package rpc;\n" +
"\n" +
"message RpcRequestMsg {\n" +
diff --git a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java
index 9f04d382fb..ac272d0bb4 100644
--- a/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java
+++ b/application/src/test/java/org/thingsboard/server/transport/lwm2m/AbstractLwM2MIntegrationTest.java
@@ -144,7 +144,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractControllerTes
" \"attributeLwm2m\": {}\n" +
" }";
- protected final String OBSERVE_ATTRIBUTES_WITH_PARAMS =
+ public static final String OBSERVE_ATTRIBUTES_WITH_PARAMS =
" {\n" +
" \"keyName\": {\n" +
@@ -159,7 +159,7 @@ public abstract class AbstractLwM2MIntegrationTest extends AbstractControllerTes
" \"attributeLwm2m\": {}\n" +
" }";
- protected final String CLIENT_LWM2M_SETTINGS =
+ public static final String CLIENT_LWM2M_SETTINGS =
" {\n" +
" \"edrxCycle\": null,\n" +
" \"powerMode\": \"DRX\",\n" +
diff --git a/common/actor/pom.xml b/common/actor/pom.xml
index a565ed9052..268b8e698b 100644
--- a/common/actor/pom.xml
+++ b/common/actor/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/cache/pom.xml b/common/cache/pom.xml
index d3f2c838c8..e2b743574f 100644
--- a/common/cache/pom.xml
+++ b/common/cache/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/cluster-api/pom.xml b/common/cluster-api/pom.xml
index 62175cae08..3df2d5e8bc 100644
--- a/common/cluster-api/pom.xml
+++ b/common/cluster-api/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/coap-server/pom.xml b/common/coap-server/pom.xml
index 5eba5c7175..596aa90e98 100644
--- a/common/coap-server/pom.xml
+++ b/common/coap-server/pom.xml
@@ -22,7 +22,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml
index 4b15effa44..c75186c0a0 100644
--- a/common/dao-api/pom.xml
+++ b/common/dao-api/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/data/pom.xml b/common/data/pom.xml
index 75758021c8..decbba55aa 100644
--- a/common/data/pom.xml
+++ b/common/data/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java
index f38749a868..e603d74198 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/CoapDeviceTransportConfiguration.java
@@ -27,6 +27,8 @@ import java.util.Map;
@Data
public class CoapDeviceTransportConfiguration extends PowerSavingConfiguration implements DeviceTransportConfiguration {
+ private static final long serialVersionUID = 6061442236008925609L;
+
@JsonIgnore
private Map properties = new HashMap<>();
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java
index 3e03dffd66..268cf2da6e 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DefaultDeviceConfiguration.java
@@ -23,6 +23,8 @@ import org.thingsboard.server.common.data.DeviceProfileType;
@Data
public class DefaultDeviceConfiguration implements DeviceConfiguration {
+ private static final long serialVersionUID = -2225378639573611325L;
+
@Override
public DeviceProfileType getType() {
return DeviceProfileType.DEFAULT;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java
index 83ed57fb84..c7f53a84c1 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceConfiguration.java
@@ -22,6 +22,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.swagger.annotations.ApiModel;
import org.thingsboard.server.common.data.DeviceProfileType;
+import java.io.Serializable;
+
@ApiModel
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
@@ -30,7 +32,7 @@ import org.thingsboard.server.common.data.DeviceProfileType;
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = DefaultDeviceConfiguration.class, name = "DEFAULT")})
-public interface DeviceConfiguration {
+public interface DeviceConfiguration extends Serializable {
@JsonIgnore
DeviceProfileType getType();
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java
index 03187f180b..8a87c18059 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/DeviceData.java
@@ -19,9 +19,13 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
+import java.io.Serializable;
+
@ApiModel
@Data
-public class DeviceData {
+public class DeviceData implements Serializable {
+
+ private static final long serialVersionUID = -3771567735290681274L;
@ApiModelProperty(position = 1, value = "Device configuration for device profile type. DEFAULT is only supported value for now")
private DeviceConfiguration configuration;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/PowerSavingConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/PowerSavingConfiguration.java
index ebed17c585..51870b67c9 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/data/PowerSavingConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/data/PowerSavingConfiguration.java
@@ -17,8 +17,13 @@ package org.thingsboard.server.common.data.device.data;
import lombok.Data;
+import java.io.Serializable;
+
@Data
-public class PowerSavingConfiguration {
+public class PowerSavingConfiguration implements Serializable {
+
+ private static final long serialVersionUID = 2905389805488525362L;
+
private PowerMode powerMode;
private Long psmActivityTimer;
private Long edrxCycle;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CoapDeviceTypeConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CoapDeviceTypeConfiguration.java
index e60f421635..a4bbe9c2c3 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CoapDeviceTypeConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/CoapDeviceTypeConfiguration.java
@@ -21,6 +21,8 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.thingsboard.server.common.data.CoapDeviceType;
+import java.io.Serializable;
+
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
@@ -29,7 +31,7 @@ import org.thingsboard.server.common.data.CoapDeviceType;
@JsonSubTypes({
@JsonSubTypes.Type(value = DefaultCoapDeviceTypeConfiguration.class, name = "DEFAULT"),
@JsonSubTypes.Type(value = EfentoCoapDeviceTypeConfiguration.class, name = "EFENTO")})
-public interface CoapDeviceTypeConfiguration {
+public interface CoapDeviceTypeConfiguration extends Serializable {
@JsonIgnore
CoapDeviceType getCoapDeviceType();
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DefaultCoapDeviceTypeConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DefaultCoapDeviceTypeConfiguration.java
index c835d58af4..cfa5c08cd1 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DefaultCoapDeviceTypeConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DefaultCoapDeviceTypeConfiguration.java
@@ -21,6 +21,8 @@ import org.thingsboard.server.common.data.CoapDeviceType;
@Data
public class DefaultCoapDeviceTypeConfiguration implements CoapDeviceTypeConfiguration {
+ private static final long serialVersionUID = -4287100699186773773L;
+
private TransportPayloadTypeConfiguration transportPayloadTypeConfiguration;
@Override
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/EfentoCoapDeviceTypeConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/EfentoCoapDeviceTypeConfiguration.java
index 4ac85b4336..29cc1983e6 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/EfentoCoapDeviceTypeConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/EfentoCoapDeviceTypeConfiguration.java
@@ -21,6 +21,8 @@ import org.thingsboard.server.common.data.CoapDeviceType;
@Data
public class EfentoCoapDeviceTypeConfiguration implements CoapDeviceTypeConfiguration {
+ private static final long serialVersionUID = -8523081152598707064L;
+
@Override
public CoapDeviceType getCoapDeviceType() {
return CoapDeviceType.EFENTO;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/ObjectAttributes.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/ObjectAttributes.java
index bcaedaa801..60245f6869 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/ObjectAttributes.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/ObjectAttributes.java
@@ -18,9 +18,13 @@ package org.thingsboard.server.common.data.device.profile.lwm2m;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
+import java.io.Serializable;
+
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
-public class ObjectAttributes {
+public class ObjectAttributes implements Serializable {
+
+ private static final long serialVersionUID = 4765123984733721312L;
private Long dim;
private String ver;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java
index 73caea088d..13bf9f4793 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/OtherConfiguration.java
@@ -18,10 +18,12 @@ package org.thingsboard.server.common.data.device.profile.lwm2m;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.device.data.PowerMode;
import org.thingsboard.server.common.data.device.data.PowerSavingConfiguration;
+@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryMappingConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryMappingConfiguration.java
index cb6f4e7695..dac6f76e6a 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryMappingConfiguration.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/TelemetryMappingConfiguration.java
@@ -19,13 +19,16 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
+import java.io.Serializable;
import java.util.Map;
import java.util.Set;
@Data
@NoArgsConstructor
@AllArgsConstructor
-public class TelemetryMappingConfiguration {
+public class TelemetryMappingConfiguration implements Serializable {
+
+ private static final long serialVersionUID = -7594999741305410419L;
private Map keyName;
private Set observe;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MBootstrapServerCredential.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MBootstrapServerCredential.java
index 6a563c8418..6367036ecb 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MBootstrapServerCredential.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MBootstrapServerCredential.java
@@ -21,6 +21,8 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
+import java.io.Serializable;
+
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "securityMode")
@@ -31,7 +33,7 @@ import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurity
@JsonSubTypes.Type(value = X509LwM2MBootstrapServerCredential.class, name = "X509")
})
@JsonIgnoreProperties(ignoreUnknown = true)
-public interface LwM2MBootstrapServerCredential {
+public interface LwM2MBootstrapServerCredential extends Serializable {
@JsonIgnore
LwM2MSecurityMode getSecurityMode();
}
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MBootstrapServersConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MBootstrapServersConfiguration.java
deleted file mode 100644
index e5bdec684a..0000000000
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/LwM2MBootstrapServersConfiguration.java
+++ /dev/null
@@ -1,27 +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.common.data.device.profile.lwm2m.bootstrap;
-
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-public class LwM2MBootstrapServersConfiguration {
-
- List bootstrap;
-
-}
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java
index 2c0e615cfb..301d033ab9 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/NoSecLwM2MBootstrapServerCredential.java
@@ -18,6 +18,9 @@ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
public class NoSecLwM2MBootstrapServerCredential extends AbstractLwM2MBootstrapServerCredential {
+
+ private static final long serialVersionUID = 5540417758424747066L;
+
@Override
public LwM2MSecurityMode getSecurityMode() {
return LwM2MSecurityMode.NO_SEC;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/PSKLwM2MBootstrapServerCredential.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/PSKLwM2MBootstrapServerCredential.java
index 08901459d2..2fd73af720 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/PSKLwM2MBootstrapServerCredential.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/PSKLwM2MBootstrapServerCredential.java
@@ -18,6 +18,9 @@ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
public class PSKLwM2MBootstrapServerCredential extends AbstractLwM2MBootstrapServerCredential {
+
+ private static final long serialVersionUID = -1639587501559199887L;
+
@Override
public LwM2MSecurityMode getSecurityMode() {
return LwM2MSecurityMode.PSK;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/RPKLwM2MBootstrapServerCredential.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/RPKLwM2MBootstrapServerCredential.java
index 477973cf6b..99ecf4dcff 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/RPKLwM2MBootstrapServerCredential.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/RPKLwM2MBootstrapServerCredential.java
@@ -18,6 +18,9 @@ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
public class RPKLwM2MBootstrapServerCredential extends AbstractLwM2MBootstrapServerCredential {
+
+ private static final long serialVersionUID = 6692464656059120166L;
+
@Override
public LwM2MSecurityMode getSecurityMode() {
return LwM2MSecurityMode.RPK;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/X509LwM2MBootstrapServerCredential.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/X509LwM2MBootstrapServerCredential.java
index 3f4e0f0aa8..a229d5fceb 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/X509LwM2MBootstrapServerCredential.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/lwm2m/bootstrap/X509LwM2MBootstrapServerCredential.java
@@ -18,6 +18,9 @@ package org.thingsboard.server.common.data.device.profile.lwm2m.bootstrap;
import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
public class X509LwM2MBootstrapServerCredential extends AbstractLwM2MBootstrapServerCredential {
+
+ private static final long serialVersionUID = -3740860424558547405L;
+
@Override
public LwM2MSecurityMode getSecurityMode() {
return LwM2MSecurityMode.X509;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java
index 376311f75b..c184b70ed4 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/SnmpMapping.java
@@ -22,12 +22,16 @@ import lombok.NoArgsConstructor;
import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.kv.DataType;
+import java.io.Serializable;
import java.util.regex.Pattern;
@Data
@AllArgsConstructor
@NoArgsConstructor
-public class SnmpMapping {
+public class SnmpMapping implements Serializable {
+
+ private static final long serialVersionUID = 2042438869374145944L;
+
private String oid;
private String key;
private DataType dataType;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/SnmpCommunicationConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/SnmpCommunicationConfig.java
index 22678620cf..6bb8c66bf2 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/SnmpCommunicationConfig.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/SnmpCommunicationConfig.java
@@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.transport.snmp.config.impl.SharedAttri
import org.thingsboard.server.common.data.transport.snmp.config.impl.TelemetryQueryingSnmpCommunicationConfig;
import org.thingsboard.server.common.data.transport.snmp.config.impl.ToDeviceRpcRequestSnmpCommunicationConfig;
+import java.io.Serializable;
import java.util.List;
@JsonIgnoreProperties(ignoreUnknown = true)
@@ -38,7 +39,7 @@ import java.util.List;
@Type(value = SharedAttributesSettingSnmpCommunicationConfig.class, name = "SHARED_ATTRIBUTES_SETTING"),
@Type(value = ToDeviceRpcRequestSnmpCommunicationConfig.class, name = "TO_DEVICE_RPC_REQUEST")
})
-public interface SnmpCommunicationConfig {
+public interface SnmpCommunicationConfig extends Serializable {
SnmpCommunicationSpec getSpec();
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ClientAttributesQueryingSnmpCommunicationConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ClientAttributesQueryingSnmpCommunicationConfig.java
index 2eec1e336c..2601e9accc 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ClientAttributesQueryingSnmpCommunicationConfig.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ClientAttributesQueryingSnmpCommunicationConfig.java
@@ -20,6 +20,8 @@ import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryin
public class ClientAttributesQueryingSnmpCommunicationConfig extends RepeatingQueryingSnmpCommunicationConfig {
+ private static final long serialVersionUID = 536740834893462914L;
+
@Override
public SnmpCommunicationSpec getSpec() {
return SnmpCommunicationSpec.CLIENT_ATTRIBUTES_QUERYING;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/SharedAttributesSettingSnmpCommunicationConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/SharedAttributesSettingSnmpCommunicationConfig.java
index c034b6c26e..b80aaf3583 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/SharedAttributesSettingSnmpCommunicationConfig.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/SharedAttributesSettingSnmpCommunicationConfig.java
@@ -21,6 +21,8 @@ import org.thingsboard.server.common.data.transport.snmp.config.MultipleMappings
public class SharedAttributesSettingSnmpCommunicationConfig extends MultipleMappingsSnmpCommunicationConfig {
+ private static final long serialVersionUID = 8981224974190924703L;
+
@Override
public SnmpCommunicationSpec getSpec() {
return SnmpCommunicationSpec.SHARED_ATTRIBUTES_SETTING;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/TelemetryQueryingSnmpCommunicationConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/TelemetryQueryingSnmpCommunicationConfig.java
index d4b16e9e0b..4b59dbd5e4 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/TelemetryQueryingSnmpCommunicationConfig.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/TelemetryQueryingSnmpCommunicationConfig.java
@@ -24,6 +24,8 @@ import org.thingsboard.server.common.data.transport.snmp.config.RepeatingQueryin
@Data
public class TelemetryQueryingSnmpCommunicationConfig extends RepeatingQueryingSnmpCommunicationConfig {
+ private static final long serialVersionUID = -1367743866881596885L;
+
@Override
public SnmpCommunicationSpec getSpec() {
return SnmpCommunicationSpec.TELEMETRY_QUERYING;
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ToDeviceRpcRequestSnmpCommunicationConfig.java b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ToDeviceRpcRequestSnmpCommunicationConfig.java
index 2a587f4243..c86c330cae 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ToDeviceRpcRequestSnmpCommunicationConfig.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/transport/snmp/config/impl/ToDeviceRpcRequestSnmpCommunicationConfig.java
@@ -19,6 +19,9 @@ import org.thingsboard.server.common.data.transport.snmp.SnmpCommunicationSpec;
import org.thingsboard.server.common.data.transport.snmp.config.MultipleMappingsSnmpCommunicationConfig;
public class ToDeviceRpcRequestSnmpCommunicationConfig extends MultipleMappingsSnmpCommunicationConfig {
+
+ private static final long serialVersionUID = -8607312598073845460L;
+
@Override
public SnmpCommunicationSpec getSpec() {
return SnmpCommunicationSpec.TO_DEVICE_RPC_REQUEST;
diff --git a/common/edge-api/pom.xml b/common/edge-api/pom.xml
index aa4a095c99..576f2aeced 100644
--- a/common/edge-api/pom.xml
+++ b/common/edge-api/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/edge-api/src/main/proto/edge.proto b/common/edge-api/src/main/proto/edge.proto
index f7ecbfcb8d..7272e6f96a 100644
--- a/common/edge-api/src/main/proto/edge.proto
+++ b/common/edge-api/src/main/proto/edge.proto
@@ -200,6 +200,7 @@ message DeviceUpdateMsg {
optional string conflictName = 12;
optional int64 firmwareIdMSB = 13;
optional int64 firmwareIdLSB = 14;
+ optional bytes deviceDataBytes = 15;
}
message DeviceProfileUpdateMsg {
diff --git a/common/message/pom.xml b/common/message/pom.xml
index ab4d73f3ee..de18be2e21 100644
--- a/common/message/pom.xml
+++ b/common/message/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/pom.xml b/common/pom.xml
index 33abef1062..770cb402d2 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
common
diff --git a/common/queue/pom.xml b/common/queue/pom.xml
index e116645618..c246ab358f 100644
--- a/common/queue/pom.xml
+++ b/common/queue/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/stats/pom.xml b/common/stats/pom.xml
index b576b8226e..d316980e97 100644
--- a/common/stats/pom.xml
+++ b/common/stats/pom.xml
@@ -22,7 +22,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml
index 6248f11a6c..70b2470dc4 100644
--- a/common/transport/coap/pom.xml
+++ b/common/transport/coap/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml
index a55dea2f2b..c0bb5d9001 100644
--- a/common/transport/http/pom.xml
+++ b/common/transport/http/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/transport/lwm2m/pom.xml b/common/transport/lwm2m/pom.xml
index 29e74a7931..d9f92d685d 100644
--- a/common/transport/lwm2m/pom.xml
+++ b/common/transport/lwm2m/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapConfig.java b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapConfig.java
index 63221f36ff..966404cce2 100644
--- a/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapConfig.java
+++ b/common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/bootstrap/secure/LwM2MBootstrapConfig.java
@@ -37,6 +37,8 @@ import java.util.List;
@Data
public class LwM2MBootstrapConfig implements Serializable {
+ private static final long serialVersionUID = -4729088085817468640L;
+
List serverConfiguration;
/** -bootstrapServer, lwm2mServer
diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml
index 2542e5914e..9906b39ba7 100644
--- a/common/transport/mqtt/pom.xml
+++ b/common/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/transport/pom.xml b/common/transport/pom.xml
index be0da470c3..125139c523 100644
--- a/common/transport/pom.xml
+++ b/common/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/transport/snmp/pom.xml b/common/transport/snmp/pom.xml
index 7bcf4dc137..c9611333f8 100644
--- a/common/transport/snmp/pom.xml
+++ b/common/transport/snmp/pom.xml
@@ -21,7 +21,7 @@
org.thingsboard.common
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml
index 308768231e..932629bb12 100644
--- a/common/transport/transport-api/pom.xml
+++ b/common/transport/transport-api/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.common
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.common.transport
diff --git a/common/util/pom.xml b/common/util/pom.xml
index cd45ff96d7..5717362ff0 100644
--- a/common/util/pom.xml
+++ b/common/util/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/common/version-control/pom.xml b/common/version-control/pom.xml
index ac472c8e3c..7929a49a3b 100644
--- a/common/version-control/pom.xml
+++ b/common/version-control/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
common
org.thingsboard.common
diff --git a/dao/pom.xml b/dao/pom.xml
index ae98928787..f911a7e043 100644
--- a/dao/pom.xml
+++ b/dao/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
dao
diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
index 714e131025..f83a66fce9 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
@@ -24,6 +24,7 @@ import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.thingsboard.common.util.ThingsBoardThreadFactory;
import org.thingsboard.server.common.data.alarm.Alarm;
@@ -142,6 +143,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
}
@Override
+ @Transactional
public AlarmOperationResult deleteAlarm(TenantId tenantId, AlarmId alarmId) {
try {
log.debug("Deleting Alarm Id: {}", alarmId);
diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
index 31c40e0d96..3ffcc999c3 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
@@ -20,10 +20,9 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import lombok.extern.slf4j.Slf4j;
-import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
@@ -150,6 +149,7 @@ public class BaseAssetService extends AbstractCachedEntityService nodeRelations = getRuleChainToNodeRelations(tenantId, ruleChainId);
for (EntityRelation relation : nodeRelations) {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java
index 8a2d3354d4..a1ffde92d5 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java
@@ -19,8 +19,6 @@ import lombok.extern.slf4j.Slf4j;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Propagation;
-import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.TenantProfile;
diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
index 866150e679..25489f3e1a 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
@@ -170,6 +170,11 @@ public class TenantServiceImpl extends AbstractCachedEntityService 0 AND regular_events_end_ts > 0 THEN
- EXECUTE format(
- 'WITH deleted AS (DELETE FROM event WHERE id in (SELECT id from event WHERE ts > %L::bigint AND ts < %L::bigint AND ' ||
- '(event_type != %L::varchar AND event_type != %L::varchar)) RETURNING *) ' ||
- 'SELECT count(*) FROM deleted', regular_events_start_ts, regular_events_end_ts,
- 'DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN') into ttl_deleted_count;
- END IF;
- IF debug_events_start_ts > 0 AND debug_events_end_ts > 0 THEN
- EXECUTE format(
- 'WITH deleted AS (DELETE FROM event WHERE id in (SELECT id from event WHERE ts > %L::bigint AND ts < %L::bigint AND ' ||
- '(event_type = %L::varchar OR event_type = %L::varchar)) RETURNING *) ' ||
- 'SELECT count(*) FROM deleted', debug_events_start_ts, debug_events_end_ts,
- 'DEBUG_RULE_NODE', 'DEBUG_RULE_CHAIN') into debug_ttl_deleted_count;
- END IF;
- RAISE NOTICE 'Events removed by ttl: %', ttl_deleted_count;
- RAISE NOTICE 'Debug Events removed by ttl: %', debug_ttl_deleted_count;
- deleted := ttl_deleted_count + debug_ttl_deleted_count;
-END
-$$;
-
CREATE OR REPLACE FUNCTION to_uuid(IN entity_id varchar, OUT uuid_id uuid) AS
$$
BEGIN
diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml
index da4e900015..a1c745e163 100644
--- a/msa/black-box-tests/pom.xml
+++ b/msa/black-box-tests/pom.xml
@@ -21,7 +21,7 @@
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json
index f220fd4ff5..dea0eb29c1 100644
--- a/msa/js-executor/package.json
+++ b/msa/js-executor/package.json
@@ -1,7 +1,7 @@
{
"name": "thingsboard-js-executor",
"private": true,
- "version": "3.4.1",
+ "version": "3.4.2",
"description": "ThingsBoard JavaScript Executor Microservice",
"main": "server.ts",
"bin": "server.js",
diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml
index b13be7048e..95a4e0c724 100644
--- a/msa/js-executor/pom.xml
+++ b/msa/js-executor/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/pom.xml b/msa/pom.xml
index 4de30d5fdf..e527566683 100644
--- a/msa/pom.xml
+++ b/msa/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
msa
diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml
index 785748957e..965d0ab05a 100644
--- a/msa/tb-node/pom.xml
+++ b/msa/tb-node/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml
index 1226f5a5ee..30358d97cb 100644
--- a/msa/tb/pom.xml
+++ b/msa/tb/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml
index 0fc536f512..3b5a91dd13 100644
--- a/msa/transport/coap/pom.xml
+++ b/msa/transport/coap/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.msa
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.msa.transport
diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml
index 00f3b19917..6fbb13f32f 100644
--- a/msa/transport/http/pom.xml
+++ b/msa/transport/http/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.msa
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.msa.transport
diff --git a/msa/transport/lwm2m/pom.xml b/msa/transport/lwm2m/pom.xml
index 746df2afc4..fa8d99e8b5 100644
--- a/msa/transport/lwm2m/pom.xml
+++ b/msa/transport/lwm2m/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.msa
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.msa.transport
diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml
index da786c014f..c63fd43668 100644
--- a/msa/transport/mqtt/pom.xml
+++ b/msa/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard.msa
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.msa.transport
diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml
index efc9093263..38f08cffaf 100644
--- a/msa/transport/pom.xml
+++ b/msa/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/transport/snmp/pom.xml b/msa/transport/snmp/pom.xml
index e2ec3d811d..8edd6dfeaa 100644
--- a/msa/transport/snmp/pom.xml
+++ b/msa/transport/snmp/pom.xml
@@ -21,7 +21,7 @@
org.thingsboard.msa
transport
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
org.thingsboard.msa.transport
diff --git a/msa/vc-executor-docker/pom.xml b/msa/vc-executor-docker/pom.xml
index c4be5c06da..38c6979c83 100644
--- a/msa/vc-executor-docker/pom.xml
+++ b/msa/vc-executor-docker/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/vc-executor/pom.xml b/msa/vc-executor/pom.xml
index bc315e8d34..2a4d07011e 100644
--- a/msa/vc-executor/pom.xml
+++ b/msa/vc-executor/pom.xml
@@ -21,7 +21,7 @@
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json
index 797ac1c9fd..4529d51510 100644
--- a/msa/web-ui/package.json
+++ b/msa/web-ui/package.json
@@ -1,7 +1,7 @@
{
"name": "thingsboard-web-ui",
"private": true,
- "version": "3.4.1",
+ "version": "3.4.2",
"description": "ThingsBoard Web UI Microservice",
"main": "server.ts",
"bin": "server.js",
diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml
index 9d9f3f8e08..872170798f 100644
--- a/msa/web-ui/pom.xml
+++ b/msa/web-ui/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
msa
org.thingsboard.msa
diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml
index 472ce55fc7..5b4c8506c6 100644
--- a/netty-mqtt/pom.xml
+++ b/netty-mqtt/pom.xml
@@ -19,11 +19,11 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
netty-mqtt
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
jar
Netty MQTT Client
diff --git a/pom.xml b/pom.xml
index 85934a5178..5fbfe077d4 100755
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
pom
Thingsboard
@@ -89,7 +89,7 @@
1.6.3
0.7
1.18.2
- 1.67
+ 1.69
2.0.1
42.2.20
org/thingsboard/server/gen/**/*,
diff --git a/rest-client/pom.xml b/rest-client/pom.xml
index 8b1d4b9641..4b9efe6177 100644
--- a/rest-client/pom.xml
+++ b/rest-client/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
rest-client
diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml
index 584bce461c..438c2d3157 100644
--- a/rule-engine/pom.xml
+++ b/rule-engine/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
rule-engine
diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml
index f3ce720866..99170b585c 100644
--- a/rule-engine/rule-engine-api/pom.xml
+++ b/rule-engine/rule-engine-api/pom.xml
@@ -22,7 +22,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
rule-engine
org.thingsboard.rule-engine
diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml
index ee32658d63..439ed41859 100644
--- a/rule-engine/rule-engine-components/pom.xml
+++ b/rule-engine/rule-engine-components/pom.xml
@@ -22,7 +22,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
rule-engine
org.thingsboard.rule-engine
diff --git a/tools/pom.xml b/tools/pom.xml
index 1b1f99d44e..850485ed42 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
tools
diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml
index 4235f1b1f5..dd151dc920 100644
--- a/transport/coap/pom.xml
+++ b/transport/coap/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/http/pom.xml b/transport/http/pom.xml
index 69ab0495c8..15a9305c76 100644
--- a/transport/http/pom.xml
+++ b/transport/http/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/lwm2m/pom.xml b/transport/lwm2m/pom.xml
index 29fd3c6fb0..b2d7809f4d 100644
--- a/transport/lwm2m/pom.xml
+++ b/transport/lwm2m/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml
index 77b4d2ad33..4115434335 100644
--- a/transport/mqtt/pom.xml
+++ b/transport/mqtt/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
org.thingsboard.transport
diff --git a/transport/pom.xml b/transport/pom.xml
index c114c031d2..d46c850c41 100644
--- a/transport/pom.xml
+++ b/transport/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
transport
diff --git a/transport/snmp/pom.xml b/transport/snmp/pom.xml
index 7fefe9f49b..57cfd4d8f0 100644
--- a/transport/snmp/pom.xml
+++ b/transport/snmp/pom.xml
@@ -21,7 +21,7 @@
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
transport
diff --git a/ui-ngx/package.json b/ui-ngx/package.json
index 44917dc47f..ea410747b2 100644
--- a/ui-ngx/package.json
+++ b/ui-ngx/package.json
@@ -1,6 +1,6 @@
{
"name": "thingsboard",
- "version": "3.4.1",
+ "version": "3.4.2",
"scripts": {
"ng": "ng",
"start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --configuration development --host 0.0.0.0 --open",
diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml
index 5bf5867398..dade6f8c28 100644
--- a/ui-ngx/pom.xml
+++ b/ui-ngx/pom.xml
@@ -20,7 +20,7 @@
4.0.0
org.thingsboard
- 3.4.1-SNAPSHOT
+ 3.4.2-SNAPSHOT
thingsboard
org.thingsboard
diff --git a/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts b/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts
index 5dfa528e9a..074381f5de 100644
--- a/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts
+++ b/ui-ngx/src/app/modules/home/components/entity/entities-table.component.ts
@@ -305,7 +305,6 @@ export class EntitiesTableComponent extends PageComponent implements IEntitiesTa
this.textSearchMode = true;
this.pageLink.textSearch = decodeURI(params.textSearch);
} else {
- this.textSearchMode = false;
this.pageLink.textSearch = null;
}
this.updateData();
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.component.ts
index 30254d079a..a37c35831f 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.component.ts
@@ -159,21 +159,21 @@ export class EntitiesHierarchyWidgetComponent extends PageComponent implements O
parentNodeCtx.level = 1;
testNodeCtx.parentNodeCtx = parentNodeCtx;
- this.nodeRelationQueryFunction = loadNodeCtxFunction(this.settings.nodeRelationQueryFunction, 'nodeCtx', testNodeCtx);
- this.nodeIconFunction = loadNodeCtxFunction(this.settings.nodeIconFunction, 'nodeCtx', testNodeCtx);
- this.nodeTextFunction = loadNodeCtxFunction(this.settings.nodeTextFunction, 'nodeCtx', testNodeCtx);
- this.nodeDisabledFunction = loadNodeCtxFunction(this.settings.nodeDisabledFunction, 'nodeCtx', testNodeCtx);
- this.nodeOpenedFunction = loadNodeCtxFunction(this.settings.nodeOpenedFunction, 'nodeCtx', testNodeCtx);
- this.nodeHasChildrenFunction = loadNodeCtxFunction(this.settings.nodeHasChildrenFunction, 'nodeCtx', testNodeCtx);
+ this.nodeRelationQueryFunction = loadNodeCtxFunction(this.settings.nodeRelationQueryFunction, 'widgetCtx, nodeCtx', this.ctx, testNodeCtx);
+ this.nodeIconFunction = loadNodeCtxFunction(this.settings.nodeIconFunction, 'widgetCtx, nodeCtx', this.ctx, testNodeCtx);
+ this.nodeTextFunction = loadNodeCtxFunction(this.settings.nodeTextFunction, 'widgetCtx, nodeCtx', this.ctx, testNodeCtx);
+ this.nodeDisabledFunction = loadNodeCtxFunction(this.settings.nodeDisabledFunction, 'widgetCtx, nodeCtx', this.ctx, testNodeCtx);
+ this.nodeOpenedFunction = loadNodeCtxFunction(this.settings.nodeOpenedFunction, 'widgetCtx, nodeCtx', this.ctx, testNodeCtx);
+ this.nodeHasChildrenFunction = loadNodeCtxFunction(this.settings.nodeHasChildrenFunction, 'widgetCtx, nodeCtx', this.ctx, testNodeCtx);
const testNodeCtx2 = deepClone(testNodeCtx);
testNodeCtx2.entity.name = 'TEST DEV2';
- this.nodesSortFunction = loadNodeCtxFunction(this.settings.nodesSortFunction, 'nodeCtx1,nodeCtx2', testNodeCtx, testNodeCtx2);
+ this.nodesSortFunction = loadNodeCtxFunction(this.settings.nodesSortFunction, 'widgetCtx, nodeCtx1,nodeCtx2', this.ctx, testNodeCtx, testNodeCtx2);
this.nodeRelationQueryFunction = this.nodeRelationQueryFunction || defaultNodeRelationQueryFunction;
this.nodeIconFunction = this.nodeIconFunction || defaultNodeIconFunction;
- this.nodeTextFunction = this.nodeTextFunction || ((nodeCtx) => nodeCtx.entity.name);
+ this.nodeTextFunction = this.nodeTextFunction || ((widgetCtx, nodeCtx) => nodeCtx.entity.name);
this.nodeDisabledFunction = this.nodeDisabledFunction || (() => false);
this.nodeOpenedFunction = this.nodeOpenedFunction || defaultNodeOpenedFunction;
this.nodeHasChildrenFunction = this.nodeHasChildrenFunction || (() => true);
@@ -322,7 +322,7 @@ export class EntitiesHierarchyWidgetComponent extends PageComponent implements O
node.text = newText;
this.nodeEditCallbacks.updateNode(node.id, node.text);
}
- const newDisabled = this.nodeDisabledFunction(node.data.nodeCtx);
+ const newDisabled = this.nodeDisabledFunction(this.ctx, node.data.nodeCtx);
if (node.state.disabled !== newDisabled) {
node.state.disabled = newDisabled;
if (node.state.disabled) {
@@ -331,7 +331,7 @@ export class EntitiesHierarchyWidgetComponent extends PageComponent implements O
this.nodeEditCallbacks.enableNode(node.id);
}
}
- const newHasChildren = this.nodeHasChildrenFunction(node.data.nodeCtx);
+ const newHasChildren = this.nodeHasChildrenFunction(this.ctx, node.data.nodeCtx);
if (node.children !== newHasChildren) {
node.children = newHasChildren;
this.nodeEditCallbacks.setNodeHasChildren(node.id, node.children);
@@ -340,22 +340,22 @@ export class EntitiesHierarchyWidgetComponent extends PageComponent implements O
private prepareNodes(nodes: HierarchyNavTreeNode[]): HierarchyNavTreeNode[] {
nodes = nodes.filter((node) => node !== null);
- nodes.sort((node1, node2) => this.nodesSortFunction(node1.data.nodeCtx, node2.data.nodeCtx));
+ nodes.sort((node1, node2) => this.nodesSortFunction(this.ctx, node1.data.nodeCtx, node2.data.nodeCtx));
return nodes;
}
private prepareNodeText(node: HierarchyNavTreeNode): string {
const nodeIcon = this.prepareNodeIcon(node.data.nodeCtx);
- const nodeText = this.nodeTextFunction(node.data.nodeCtx);
+ const nodeText = this.nodeTextFunction(this.ctx, node.data.nodeCtx);
node.data.searchText = nodeText ? nodeText.replace(/<[^>]+>/g, '').toLowerCase() : '';
return nodeIcon + nodeText;
}
private prepareNodeIcon(nodeCtx: HierarchyNodeContext): string {
- let iconInfo = this.nodeIconFunction(nodeCtx);
+ let iconInfo = this.nodeIconFunction(this.ctx, nodeCtx);
if (iconInfo) {
if (iconInfo === 'default') {
- iconInfo = defaultNodeIconFunction(nodeCtx);
+ iconInfo = defaultNodeIconFunction(this.ctx, nodeCtx);
}
if (iconInfo && iconInfo !== 'default' && (iconInfo.iconUrl || iconInfo.materialIcon)) {
if (iconInfo.materialIcon) {
@@ -406,11 +406,11 @@ export class EntitiesHierarchyWidgetComponent extends PageComponent implements O
nodeCtx
};
node.state = {
- disabled: this.nodeDisabledFunction(node.data.nodeCtx),
- opened: this.nodeOpenedFunction(node.data.nodeCtx)
+ disabled: this.nodeDisabledFunction(this.ctx, node.data.nodeCtx),
+ opened: this.nodeOpenedFunction(this.ctx, node.data.nodeCtx)
};
node.text = this.prepareNodeText(node);
- node.children = this.nodeHasChildrenFunction(node.data.nodeCtx);
+ node.children = this.nodeHasChildrenFunction(this.ctx, node.data.nodeCtx);
return node;
}
@@ -456,9 +456,9 @@ export class EntitiesHierarchyWidgetComponent extends PageComponent implements O
}
private prepareNodeRelationQuery(nodeCtx: HierarchyNodeContext): EntityRelationsQuery {
- let relationQuery = this.nodeRelationQueryFunction(nodeCtx);
+ let relationQuery = this.nodeRelationQueryFunction(this.ctx, nodeCtx);
if (relationQuery && relationQuery === 'default') {
- relationQuery = defaultNodeRelationQueryFunction(nodeCtx);
+ relationQuery = defaultNodeRelationQueryFunction(this.ctx, nodeCtx);
}
return relationQuery as EntityRelationsQuery;
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts
index 5e2031ec11..fcfcef8bab 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/entities-hierarchy-widget.models.ts
@@ -21,6 +21,7 @@ import { Datasource } from '@shared/models/widget.models';
import { isDefined, isUndefined } from '@core/utils';
import { EntityRelationsQuery, EntitySearchDirection, RelationTypeGroup } from '@shared/models/relation.models';
import { EntityType } from '@shared/models/entity-type.models';
+import { WidgetContext } from '@home/models/widget-component.models';
export interface EntitiesHierarchyWidgetSettings {
nodeRelationQueryFunction: string;
@@ -57,13 +58,13 @@ export interface HierarchyNodeIconInfo {
materialIcon?: string;
}
-export type NodeRelationQueryFunction = (nodeCtx: HierarchyNodeContext) => EntityRelationsQuery | 'default';
-export type NodeTextFunction = (nodeCtx: HierarchyNodeContext) => string;
-export type NodeDisabledFunction = (nodeCtx: HierarchyNodeContext) => boolean;
-export type NodeIconFunction = (nodeCtx: HierarchyNodeContext) => HierarchyNodeIconInfo | 'default';
-export type NodeOpenedFunction = (nodeCtx: HierarchyNodeContext) => boolean;
-export type NodeHasChildrenFunction = (nodeCtx: HierarchyNodeContext) => boolean;
-export type NodesSortFunction = (nodeCtx1: HierarchyNodeContext, nodeCtx2: HierarchyNodeContext) => number;
+export type NodeRelationQueryFunction = (widgetCtx: WidgetContext, nodeCtx: HierarchyNodeContext) => EntityRelationsQuery | 'default';
+export type NodeTextFunction = (widgetCtx: WidgetContext, nodeCtx: HierarchyNodeContext) => string;
+export type NodeDisabledFunction = (widgetCtx: WidgetContext, nodeCtx: HierarchyNodeContext) => boolean;
+export type NodeIconFunction = (widgetCtx: WidgetContext, nodeCtx: HierarchyNodeContext) => HierarchyNodeIconInfo | 'default';
+export type NodeOpenedFunction = (widgetCtx: WidgetContext, nodeCtx: HierarchyNodeContext) => boolean;
+export type NodeHasChildrenFunction = (widgetCtx: WidgetContext, nodeCtx: HierarchyNodeContext) => boolean;
+export type NodesSortFunction = (widgetCtx: WidgetContext, nodeCtx1: HierarchyNodeContext, nodeCtx2: HierarchyNodeContext) => number;
export function loadNodeCtxFunction any>(functionBody: string, argNames: string, ...args: any[]): F {
let nodeCtxFunction: F = null;
@@ -89,7 +90,7 @@ export function iconUrlHtml(iconUrl: string): string {
return '
';
}
-export const defaultNodeRelationQueryFunction: NodeRelationQueryFunction = nodeCtx => {
+export const defaultNodeRelationQueryFunction: NodeRelationQueryFunction = (widgetContext, nodeCtx) => {
const entity = nodeCtx.entity;
const query: EntityRelationsQuery = {
parameters: {
@@ -109,7 +110,7 @@ export const defaultNodeRelationQueryFunction: NodeRelationQueryFunction = nodeC
return query;
};
-export const defaultNodeIconFunction: NodeIconFunction = nodeCtx => {
+export const defaultNodeIconFunction: NodeIconFunction = (widgetContext, nodeCtx) => {
let materialIcon = 'insert_drive_file';
const entity = nodeCtx.entity;
if (entity && entity.id && entity.id.entityType) {
@@ -148,11 +149,11 @@ export const defaultNodeIconFunction: NodeIconFunction = nodeCtx => {
};
};
-export const defaultNodeOpenedFunction: NodeOpenedFunction = nodeCtx => {
+export const defaultNodeOpenedFunction: NodeOpenedFunction = (widgetCtx, nodeCtx) => {
return nodeCtx.level <= 4;
};
-export const defaultNodesSortFunction: NodesSortFunction = (nodeCtx1, nodeCtx2) => {
+export const defaultNodesSortFunction: NodesSortFunction = (widgetCtx, nodeCtx1, nodeCtx2) => {
let result = 0;
if (!nodeCtx1.entity.id.entityType || !nodeCtx2.entity.id.entityType ) {
if (nodeCtx1.entity.id.entityType) {
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts
index 1de38e2959..bf59e36804 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/flot-widget.ts
@@ -153,13 +153,13 @@ export class TbFlot {
autoHighlight: this.tooltipIndividual === true,
markings: []
},
- selection : { mode : 'x' },
legend : {
show: false
}
};
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'state') {
+ this.options.selection = { mode : 'x' };
this.options.xaxes = [];
this.xaxis = {
mode: 'time',
@@ -1206,10 +1206,12 @@ export class TbFlot {
private enableMouseEvents() {
this.$element.css('pointer-events', '');
this.$element.addClass('mouse-events');
- this.options.selection = { mode : 'x' };
+ if (this.chartType !== 'pie') {
+ this.options.selection = {mode: 'x'};
+ this.$element.bind('plotselected', this.flotSelectHandler);
+ this.$element.bind('dblclick', this.dblclickHandler);
+ }
this.$element.bind('plothover', this.flotHoverHandler);
- this.$element.bind('plotselected', this.flotSelectHandler);
- this.$element.bind('dblclick', this.dblclickHandler);
this.$element.bind('mousedown', this.mousedownHandler);
this.$element.bind('mouseup', this.mouseupHandler);
this.$element.bind('mouseleave', this.mouseleaveHandler);
@@ -1219,10 +1221,12 @@ export class TbFlot {
private disableMouseEvents() {
this.$element.css('pointer-events', 'none');
this.$element.removeClass('mouse-events');
- this.options.selection = { mode : null };
+ if (this.chartType !== 'pie') {
+ this.options.selection = {mode: null};
+ this.$element.unbind('plotselected', this.flotSelectHandler);
+ this.$element.unbind('dblclick', this.dblclickHandler);
+ }
this.$element.unbind('plothover', this.flotHoverHandler);
- this.$element.unbind('plotselected', this.flotSelectHandler);
- this.$element.unbind('dblclick', this.dblclickHandler);
this.$element.unbind('mousedown', this.mousedownHandler);
this.$element.unbind('mouseup', this.mouseupHandler);
this.$element.unbind('mouseleave', this.mouseleaveHandler);
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/circle.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/circle.ts
index b5f47103f0..d50a62bc9a 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/circle.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/circle.ts
@@ -102,7 +102,7 @@ export class Circle {
const circleLabelText = fillDataPattern(this.map.circleLabelText, this.map.replaceInfoTooltipCircle, this.data);
const labelColor = this.map.ctx.widgetConfig.color;
this.leafletCircle.bindTooltip(`${circleLabelText}
`,
- { className: 'tb-polygon-label', permanent: true, sticky: true, direction: 'center'})
+ { className: 'tb-polygon-label', permanent: true, direction: 'center'})
.openTooltip(this.leafletCircle.getLatLng());
}
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
index 3ef89b5031..121a6aabce 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/leaflet-map.ts
@@ -334,6 +334,7 @@ export default abstract class LeafletMap {
drawRectangle: false,
drawPolyline: false,
drawPolygon: false,
+ drawText: false,
dragMode: !this.options.hideEditControlButton,
editMode: (this.editPolygons || this.editCircle) && !this.options.hideEditControlButton,
cutPolygon: false,
@@ -493,12 +494,12 @@ export default abstract class LeafletMap {
.find('a[role="button"]:not(.leaflet-pm-action)')
.each((index, element) => {
let title;
- if (element.children.length) {
- title = (element.children[0] as HTMLElement).title;
- $(element).children().removeAttr('title');
- } else {
+ if (element.title) {
title = element.title;
$(element).removeAttr('title');
+ } else if (element.parentElement.title) {
+ title = element.parentElement.title;
+ $(element).parent().removeAttr('title');
}
const tooltip = $(element).tooltipster(
{
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
index 528172b2ba..f8e42d34e1 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/maps-utils.ts
@@ -45,6 +45,9 @@ export function createTooltip(target: L.Layer,
}
target.on('popupopen', () => {
bindPopupActions(popup, settings, datasource);
+ (target as any)._popup._closeButton.addEventListener('click', (event: Event) => {
+ event.preventDefault();
+ });
});
return popup;
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts
index 45269da5c7..9b08c7dbcd 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/maps/polygon.ts
@@ -110,7 +110,7 @@ export class Polygon {
const polygonLabelText = fillDataPattern(this.map.polygonLabelText, this.map.replaceInfoLabelPolygon, this.data);
const labelColor = this.map.ctx.widgetConfig.color;
this.leafletPoly.bindTooltip(`${polygonLabelText}
`,
- { className: 'tb-polygon-label', permanent: true, sticky: true, direction: 'center' })
+ { className: 'tb-polygon-label', permanent: true, direction: 'center' })
.openTooltip(this.leafletPoly.getBounds().getCenter());
}
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.html
index 2a2f16d581..4c65f5f1e9 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.html
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/entities-hierarchy-widget-settings.component.html
@@ -20,13 +20,13 @@
@@ -35,13 +35,13 @@
@@ -50,13 +50,13 @@
@@ -65,7 +65,7 @@
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts
index 59667b7b77..bca0fee943 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/cards/markdown-widget-settings.component.ts
@@ -51,7 +51,7 @@ export class MarkdownWidgetSettingsComponent extends WidgetSettingsComponent {
this.markdownWidgetSettingsForm = this.fb.group({
useMarkdownTextFunction: [settings.useMarkdownTextFunction, []],
markdownTextPattern: [settings.markdownTextPattern, []],
- markdownTextFunction: [settings.qrCodeTextFunction, []],
+ markdownTextFunction: [settings.markdownTextFunction, []],
markdownCss: [settings.markdownCss, []]
});
}
diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
index 67541e82cd..38b14fe485 100644
--- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
@@ -540,6 +540,9 @@ export class WidgetComponentService {
if (isUndefined(result.typeParameters.stateData)) {
result.typeParameters.stateData = false;
}
+ if (isUndefined(result.typeParameters.processNoDataByWidget)) {
+ result.typeParameters.processNoDataByWidget = false;
+ }
if (isFunction(widgetTypeInstance.actionSources)) {
result.actionSources = widgetTypeInstance.actionSources();
} else {
diff --git a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts
index 11f168a3b0..8826ff860f 100644
--- a/ui-ngx/src/app/modules/home/components/widget/widget.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/widget.component.ts
@@ -400,17 +400,17 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
}
private displayWidgetInstance(): boolean {
- if (this.widget.type !== widgetType.static) {
- for (const id of Object.keys(this.widgetContext.subscriptions)) {
- const subscription = this.widgetContext.subscriptions[id];
- if (subscription.isDataResolved()) {
- return true;
- }
- }
- return false;
- } else {
+ if (this.widget.type === widgetType.static || this.typeParameters?.processNoDataByWidget) {
return true;
}
+
+ for (const id of Object.keys(this.widgetContext.subscriptions)) {
+ const subscription = this.widgetContext.subscriptions[id];
+ if (subscription.isDataResolved()) {
+ return true;
+ }
+ }
+ return false;
}
private onDestroy() {
diff --git a/ui-ngx/src/app/shared/adapter/custom-datatime-adapter.ts b/ui-ngx/src/app/shared/adapter/custom-datatime-adapter.ts
new file mode 100644
index 0000000000..50417a5914
--- /dev/null
+++ b/ui-ngx/src/app/shared/adapter/custom-datatime-adapter.ts
@@ -0,0 +1,36 @@
+///
+/// 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.
+///
+
+import { Injectable } from '@angular/core';
+import { NativeDatetimeAdapter } from '@mat-datetimepicker/core';
+
+@Injectable()
+export class CustomDateAdapter extends NativeDatetimeAdapter {
+
+ parse(value: string | number): Date {
+ if (typeof value === 'number') {
+ return new Date(value);
+ }
+ let newDate = value;
+ const formatToParts = Intl.DateTimeFormat(this.locale).formatToParts();
+ if (formatToParts[0].type.toLowerCase() === 'day') {
+ const literal = formatToParts[1].value;
+ newDate = newDate.replace(new RegExp(`(\\d+[${literal}])(\\d+[${literal}])`), '$2$1');
+ }
+ return newDate ? new Date(Date.parse(newDate)) : null;
+ }
+
+}
diff --git a/ui-ngx/src/app/shared/components/file-input.component.ts b/ui-ngx/src/app/shared/components/file-input.component.ts
index ad2fd9f65e..deee44596c 100644
--- a/ui-ngx/src/app/shared/components/file-input.component.ts
+++ b/ui-ngx/src/app/shared/components/file-input.component.ts
@@ -188,20 +188,18 @@ export class FileInputComponent extends PageComponent implements AfterViewInit,
let fileName = null;
let fileContent = null;
let files = null;
- if (typeof reader.result === 'string') {
- fileContent = reader.result;
- if (fileContent && fileContent.length > 0) {
- if (!this.workFromFileObj) {
+ if (reader.readyState === reader.DONE) {
+ if (!this.workFromFileObj) {
+ fileContent = reader.result;
+ if (fileContent && fileContent.length > 0) {
if (this.contentConvertFunction) {
fileContent = this.contentConvertFunction(fileContent);
}
- if (fileContent) {
- fileName = file.name;
- }
- } else {
- files = file.file;
- fileName = file.name;
+ fileName = fileContent ? file.name : null;
}
+ } else if (file.name || file.file){
+ files = file.file;
+ fileName = file.name;
}
}
resolve({fileContent, fileName, files});
diff --git a/ui-ngx/src/app/shared/models/widget.models.ts b/ui-ngx/src/app/shared/models/widget.models.ts
index 35b3b0fc21..f8991f55c7 100644
--- a/ui-ngx/src/app/shared/models/widget.models.ts
+++ b/ui-ngx/src/app/shared/models/widget.models.ts
@@ -173,7 +173,7 @@ export interface WidgetTypeParameters {
hasAdditionalLatestDataKeys?: boolean;
warnOnPageDataOverflow?: boolean;
ignoreDataUpdateOnIntervalTick?: boolean;
-
+ processNoDataByWidget?: boolean;
}
export interface WidgetControllerDescriptor {
diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts
index ed26548b15..8cb71e0d9d 100644
--- a/ui-ngx/src/app/shared/shared.module.ts
+++ b/ui-ngx/src/app/shared/shared.module.ts
@@ -53,7 +53,7 @@ import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatListModule } from '@angular/material/list';
-import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core';
+import { DatetimeAdapter, MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core';
import { NgxDaterangepickerMd } from 'ngx-daterangepicker-material';
import { GridsterModule } from 'angular-gridster2';
import { FlexLayoutModule } from '@angular/flex-layout';
@@ -165,6 +165,7 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
import { MultipleImageInputComponent } from '@shared/components/multiple-image-input.component';
import { BranchAutocompleteComponent } from '@shared/components/vc/branch-autocomplete.component';
import { PhoneInputComponent } from '@shared/components/phone-input.component';
+import { CustomDateAdapter } from '@shared/adapter/custom-datatime-adapter';
import { CustomPaginatorIntl } from '@shared/services/custom-paginator-intl';
export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) {
@@ -189,6 +190,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
provide: MAT_DATE_LOCALE,
useValue: 'en-GB'
},
+ { provide: DatetimeAdapter, useClass: CustomDateAdapter },
{ provide: HELP_MARKDOWN_COMPONENT_TOKEN, useValue: HelpMarkdownComponent },
{ provide: SHARED_MODULE_TOKEN, useValue: SharedModule },
{ provide: MatPaginatorIntl, useClass: CustomPaginatorIntl },
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_disabled_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_disabled_fn.md
index b532cfa3f8..7c74cccae3 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_disabled_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_disabled_fn.md
@@ -10,6 +10,9 @@ A JavaScript function evaluating whether current node should be disabled (not se
**Parameters:**
+ - widgetCtx:
WidgetContext - A reference to WidgetContext that has all necessary API
+ and data used by widget instance.
+
- nodeCtx:
HierarchyNodeContext - An
HierarchyNodeContext object
containing entity field holding basic entity properties
(ex. id, name, label) and data field holding other entity attributes/timeseries declared in widget datasource configuration.
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_has_children_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_has_children_fn.md
index 1a71858c9b..9e1888dfb0 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_has_children_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_has_children_fn.md
@@ -10,6 +10,9 @@ A JavaScript function evaluating whether current node has children (whether it c
**Parameters:**
+ - widgetCtx:
WidgetContext - A reference to WidgetContext that has all necessary API
+ and data used by widget instance.
+
- nodeCtx:
HierarchyNodeContext - An
HierarchyNodeContext object
containing entity field holding basic entity properties
(ex. id, name, label) and data field holding other entity attributes/timeseries declared in widget datasource configuration.
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_icon_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_icon_fn.md
index 1a3c0aec8e..2da8c7932c 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_icon_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_icon_fn.md
@@ -10,6 +10,9 @@ A JavaScript function used to compute node icon info.
**Parameters:**
+ - widgetCtx:
WidgetContext - A reference to WidgetContext that has all necessary API
+ and data used by widget instance.
+
- nodeCtx:
HierarchyNodeContext - An
HierarchyNodeContext object
containing entity field holding basic entity properties
(ex. id, name, label) and data field holding other entity attributes/timeseries declared in widget datasource configuration.
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_opened_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_opened_fn.md
index e85a2b1aa9..08c9607f0b 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_opened_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_opened_fn.md
@@ -10,6 +10,9 @@ A JavaScript function evaluating whether current node should be opened (expanded
**Parameters:**
+ - widgetCtx:
WidgetContext - A reference to WidgetContext that has all necessary API
+ and data used by widget instance.
+
- nodeCtx:
HierarchyNodeContext - An
HierarchyNodeContext object
containing entity field holding basic entity properties
(ex. id, name, label) and data field holding other entity attributes/timeseries declared in widget datasource configuration.
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_relation_query_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_relation_query_fn.md
index f312483d07..2120fe4eea 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_relation_query_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_relation_query_fn.md
@@ -10,6 +10,9 @@ A JavaScript function used to compute child nodes relations query for current no
**Parameters:**
+ - widgetCtx:
WidgetContext - A reference to WidgetContext that has all necessary API
+ and data used by widget instance.
+
- nodeCtx:
HierarchyNodeContext - An
HierarchyNodeContext object
containing entity field holding basic entity properties
(ex. id, name, label) and data field holding other entity attributes/timeseries declared in widget datasource configuration.
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_text_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_text_fn.md
index 76b70a73fb..5ce79b7d15 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_text_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/node_text_fn.md
@@ -10,6 +10,9 @@ A JavaScript function used to compute text or HTML code for the current node.
**Parameters:**
+ - widgetCtx:
WidgetContext - A reference to WidgetContext that has all necessary API
+ and data used by widget instance.
+
- nodeCtx:
HierarchyNodeContext - An
HierarchyNodeContext object
containing entity field holding basic entity properties
(ex. id, name, label) and data field holding other entity attributes/timeseries declared in widget datasource configuration.
diff --git a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/nodes_sort_fn.md b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/nodes_sort_fn.md
index 779424b553..2c2375f1e4 100644
--- a/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/nodes_sort_fn.md
+++ b/ui-ngx/src/assets/help/en_US/widget/lib/entities_hierarchy/nodes_sort_fn.md
@@ -10,6 +10,9 @@ A JavaScript function used to compare nodes of the same level when sorting.
**Parameters:**