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 @@ widgets.entities-hierarchy.hierarchy-data-settings @@ -35,13 +35,13 @@ widgets.entities-hierarchy.node-state-settings @@ -50,13 +50,13 @@ widgets.entities-hierarchy.display-settings @@ -65,7 +65,7 @@ widgets.entities-hierarchy.sort-settings 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:**