From dcbc4c5c7d5ccb040fb33d7a6a8ee30b957986a7 Mon Sep 17 00:00:00 2001 From: Andrii Shvaika Date: Thu, 27 Apr 2023 19:09:56 +0300 Subject: [PATCH] Device Info Filter --- .../main/data/upgrade/3.4.4/schema_update.sql | 15 +++ .../controller/ControllerConstants.java | 1 + .../server/controller/DeviceController.java | 29 +++-- .../server/dao/device/DeviceService.java | 13 +- .../server/common/data/DeviceInfo.java | 5 +- .../server/common/data/DeviceInfoFilter.java | 34 ++++++ .../org/thingsboard/server/dao/DaoUtil.java | 36 ++++++ .../server/dao/device/DeviceDao.java | 64 +--------- .../server/dao/device/DeviceServiceImpl.java | 62 ++-------- .../server/dao/model/ModelConstants.java | 8 ++ .../thingsboard/server/dao/model/ToData.java | 4 + .../dao/model/sql/DeviceInfoEntity.java | 47 +++++--- .../server/dao/sql/alarm/JpaAlarmDao.java | 28 +---- .../dao/sql/device/DeviceRepository.java | 114 +++++------------- .../server/dao/sql/device/JpaDeviceDao.java | 84 +++++-------- .../main/resources/sql/schema-entities.sql | 10 ++ .../dao/service/BaseDeviceServiceTest.java | 33 ++--- 17 files changed, 253 insertions(+), 334 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfoFilter.java diff --git a/application/src/main/data/upgrade/3.4.4/schema_update.sql b/application/src/main/data/upgrade/3.4.4/schema_update.sql index a248766c7e..be3d70b163 100644 --- a/application/src/main/data/upgrade/3.4.4/schema_update.sql +++ b/application/src/main/data/upgrade/3.4.4/schema_update.sql @@ -14,6 +14,21 @@ -- limitations under the License. -- +-- DEVICE INFO VIEW START + +DROP VIEW IF EXISTS device_info_view CASCADE; +CREATE OR REPLACE VIEW device_info_view as +SELECT d.* + , c.title as customer_title + , c.additional_info::json->>'isPublic' as customer_is_public + , d.type as device_profile_name + , (select bool_v from attribute_kv da where da.entity_id = d.id and da.attribute_key = 'active') as attribute_active + , (select bool_v from ts_kv_latest dt where dt.entity_id = d.id and dt.key = (select key_id from ts_kv_dictionary where key = 'active')) as ts_active +FROM device d + LEFT JOIN customer c ON c.id = d.customer_id; + +-- DEVICE INFO VIEW END + -- USER CREDENTIALS START ALTER TABLE user_credentials diff --git a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java index a060335713..f425bde86c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java +++ b/application/src/main/java/org/thingsboard/server/controller/ControllerConstants.java @@ -66,6 +66,7 @@ public class ControllerConstants { protected static final String PAGE_SIZE_DESCRIPTION = "Maximum amount of entities in a one page"; protected static final String PAGE_NUMBER_DESCRIPTION = "Sequence number of page starting from 0"; protected static final String DEVICE_TYPE_DESCRIPTION = "Device type as the name of the device profile"; + protected static final String DEVICE_ACTIVE_PARAM_DESCRIPTION = "A boolean value representing the device active flag."; protected static final String ENTITY_VIEW_TYPE_DESCRIPTION = "Entity View type"; protected static final String ASSET_TYPE_DESCRIPTION = "Asset type"; protected static final String EDGE_TYPE_DESCRIPTION = "A string value representing the edge type. For example, 'default'"; diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index 0e6e19ad8d..d68aed4284 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceInfo; +import org.thingsboard.server.common.data.DeviceInfoFilter; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.SaveDeviceWithCredentialsRequest; import org.thingsboard.server.common.data.Tenant; @@ -83,6 +84,7 @@ import java.util.stream.Collectors; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_AUTHORITY_PARAGRAPH; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID; import static org.thingsboard.server.controller.ControllerConstants.CUSTOMER_ID_PARAM_DESCRIPTION; +import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ACTIVE_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_ID_PARAM_DESCRIPTION; import static org.thingsboard.server.controller.ControllerConstants.DEVICE_INFO_DESCRIPTION; @@ -333,6 +335,8 @@ public class DeviceController extends BaseController { @RequestParam(required = false) String type, @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(required = false) String deviceProfileId, + @ApiParam(value = DEVICE_ACTIVE_PARAM_DESCRIPTION) + @RequestParam(required = false) Boolean active, @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES) @@ -342,14 +346,15 @@ public class DeviceController extends BaseController { ) throws ThingsboardException { TenantId tenantId = getCurrentUser().getTenantId(); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); + DeviceInfoFilter.DeviceInfoFilterBuilder filter = DeviceInfoFilter.builder(); + filter.tenantId(tenantId); + filter.active(active); if (type != null && type.trim().length() > 0) { - return checkNotNull(deviceService.findDeviceInfosByTenantIdAndType(tenantId, type, pageLink)); + filter.type(type); } else if (deviceProfileId != null && deviceProfileId.length() > 0) { - DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId)); - return checkNotNull(deviceService.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId, profileId, pageLink)); - } else { - return checkNotNull(deviceService.findDeviceInfosByTenantId(tenantId, pageLink)); + filter.deviceProfileId(new DeviceProfileId(toUUID(deviceProfileId))); } + return checkNotNull(deviceService.findDeviceInfosByFilter(filter.build(), pageLink)); } @ApiOperation(value = "Get Tenant Device (getTenantDevice)", @@ -415,6 +420,8 @@ public class DeviceController extends BaseController { @RequestParam(required = false) String type, @ApiParam(value = DEVICE_PROFILE_ID_PARAM_DESCRIPTION) @RequestParam(required = false) String deviceProfileId, + @ApiParam(value = DEVICE_ACTIVE_PARAM_DESCRIPTION) + @RequestParam(required = false) Boolean active, @ApiParam(value = DEVICE_TEXT_SEARCH_DESCRIPTION) @RequestParam(required = false) String textSearch, @ApiParam(value = SORT_PROPERTY_DESCRIPTION, allowableValues = DEVICE_SORT_PROPERTY_ALLOWABLE_VALUES) @@ -426,14 +433,16 @@ public class DeviceController extends BaseController { CustomerId customerId = new CustomerId(toUUID(strCustomerId)); checkCustomerId(customerId, Operation.READ); PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); + DeviceInfoFilter.DeviceInfoFilterBuilder filter = DeviceInfoFilter.builder(); + filter.tenantId(tenantId); + filter.customerId(customerId); + filter.active(active); if (type != null && type.trim().length() > 0) { - return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); + filter.type(type); } else if (deviceProfileId != null && deviceProfileId.length() > 0) { - DeviceProfileId profileId = new DeviceProfileId(toUUID(deviceProfileId)); - return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId, customerId, profileId, pageLink)); - } else { - return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink)); + filter.deviceProfileId(new DeviceProfileId(toUUID(deviceProfileId))); } + return checkNotNull(deviceService.findDeviceInfosByFilter(filter.build(), pageLink)); } @ApiOperation(value = "Get Devices By Ids (getDevicesByIds)", diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java index 4383ccc0a7..a90ea9a572 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceService.java @@ -19,6 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceIdInfo; import org.thingsboard.server.common.data.DeviceInfo; +import org.thingsboard.server.common.data.DeviceInfoFilter; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.EntitySubtype; @@ -66,7 +67,7 @@ public interface DeviceService extends EntityDaoService { PageData findDevicesByTenantId(TenantId tenantId, PageLink pageLink); - PageData findDeviceInfosByTenantId(TenantId tenantId, PageLink pageLink); + PageData findDeviceInfosByFilter(DeviceInfoFilter filter, PageLink pageLink); PageData findDeviceIdInfos(PageLink pageLink); @@ -76,10 +77,6 @@ public interface DeviceService extends EntityDaoService { Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType otaPackageType); - PageData findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); - - PageData findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink); - ListenableFuture> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List deviceIds); List findDevicesByIds(List deviceIds); @@ -90,14 +87,8 @@ public interface DeviceService extends EntityDaoService { PageData findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); - PageData findDeviceInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); - PageData findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); - PageData findDeviceInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); - - PageData findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(TenantId tenantId, CustomerId customerId, DeviceProfileId deviceProfileId, PageLink pageLink); - ListenableFuture> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List deviceIds); void unassignCustomerDevices(TenantId tenantId, CustomerId customerId); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java index ee11726923..c1ffbeb79e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java @@ -30,6 +30,8 @@ public class DeviceInfo extends Device { private boolean customerIsPublic; @ApiModelProperty(position = 15, value = "Name of the corresponding Device Profile.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) private String deviceProfileName; + @ApiModelProperty(position = 16, value = "Device active flag.", accessMode = ApiModelProperty.AccessMode.READ_ONLY) + private boolean active; public DeviceInfo() { super(); @@ -39,10 +41,11 @@ public class DeviceInfo extends Device { super(deviceId); } - public DeviceInfo(Device device, String customerTitle, boolean customerIsPublic, String deviceProfileName) { + public DeviceInfo(Device device, String customerTitle, boolean customerIsPublic, String deviceProfileName, boolean active) { super(device); this.customerTitle = customerTitle; this.customerIsPublic = customerIsPublic; this.deviceProfileName = deviceProfileName; + this.active = active; } } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfoFilter.java b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfoFilter.java new file mode 100644 index 0000000000..4d5f6e0006 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfoFilter.java @@ -0,0 +1,34 @@ +/** + * Copyright © 2016-2023 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; + +import lombok.Builder; +import lombok.Data; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.TenantId; + +@Data +@Builder +public class DeviceInfoFilter { + + private TenantId tenantId; + private CustomerId customerId; + private String type; + private DeviceProfileId deviceProfileId; + private Boolean active; + +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java index 5c45e4d44b..95f3eab209 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java +++ b/dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java @@ -18,6 +18,7 @@ package org.thingsboard.server.dao; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.page.PageData; @@ -45,6 +46,12 @@ public abstract class DaoUtil { return new PageData<>(data, page.getTotalPages(), page.getTotalElements(), page.hasNext()); } + public static PageData toPageData(Page> page, Object... params) { + List data = convertDataList(page.getContent(), params); + return new PageData<>(data, page.getTotalPages(), page.getTotalElements(), page.hasNext()); + } + + public static PageData pageToPageData(Page page) { return new PageData<>(page.getContent(), page.getTotalPages(), page.getTotalElements(), page.hasNext()); } @@ -78,6 +85,19 @@ public abstract class DaoUtil { return list; } + public static List convertDataList(Collection> toDataList, Object... params) { + List list = Collections.emptyList(); + if (toDataList != null && !toDataList.isEmpty()) { + list = new ArrayList<>(); + for (ToData object : toDataList) { + if (object != null) { + list.add(object.toData(params)); + } + } + } + return list; + } + public static T getData(ToData data) { T object = null; if (data != null) { @@ -86,6 +106,15 @@ public abstract class DaoUtil { return object; } + public static T getData(ToData data, Object... params) { + T object = null; + if (data != null) { + object = data.toData(params); + } + return object; + } + + public static T getData(Optional> data) { T object = null; if (data.isPresent()) { @@ -128,4 +157,11 @@ public abstract class DaoUtil { } while (hasNextBatch); } + public static String getStringId(UUIDBased id) { + if (id != null) { + return id.toString(); + } else { + return null; + } + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java index ecdeb9e90f..f89541c77a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.device; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceInfo; +import org.thingsboard.server.common.data.DeviceInfoFilter; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.DeviceIdInfo; @@ -74,15 +75,6 @@ public interface DeviceDao extends Dao, TenantEntityDao, ExportableEntit */ PageData findDevicesByTenantId(UUID tenantId, PageLink pageLink); - /** - * Find device infos by tenantId and page link. - * - * @param tenantId the tenantId - * @param pageLink the page link - * @return the list of device info objects - */ - PageData findDeviceInfosByTenantId(UUID tenantId, PageLink pageLink); - /** * Find devices by tenantId, type and page link. * @@ -100,26 +92,6 @@ public interface DeviceDao extends Dao, TenantEntityDao, ExportableEntit Long countDevicesByTenantIdAndDeviceProfileIdAndEmptyOtaPackage(UUID tenantId, UUID deviceProfileId, OtaPackageType otaPackageType); - /** - * Find device infos by tenantId, type and page link. - * - * @param tenantId the tenantId - * @param type the type - * @param pageLink the page link - * @return the list of device info objects - */ - PageData findDeviceInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink); - - /** - * Find device infos by tenantId, deviceProfileId and page link. - * - * @param tenantId the tenantId - * @param deviceProfileId the deviceProfileId - * @param pageLink the page link - * @return the list of device info objects - */ - PageData findDeviceInfosByTenantIdAndDeviceProfileId(UUID tenantId, UUID deviceProfileId, PageLink pageLink); - /** * Find devices by tenantId and devices Ids. * @@ -155,16 +127,6 @@ public interface DeviceDao extends Dao, TenantEntityDao, ExportableEntit */ PageData findDevicesByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink); - /** - * Find device infos by tenantId, customerId and page link. - * - * @param tenantId the tenantId - * @param customerId the customerId - * @param pageLink the page link - * @return the list of device info objects - */ - PageData findDeviceInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink); - /** * Find devices by tenantId, customerId, type and page link. * @@ -176,28 +138,6 @@ public interface DeviceDao extends Dao, TenantEntityDao, ExportableEntit */ PageData findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink); - /** - * Find device infos by tenantId, customerId, type and page link. - * - * @param tenantId the tenantId - * @param customerId the customerId - * @param type the type - * @param pageLink the page link - * @return the list of device info objects - */ - PageData findDeviceInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink); - - /** - * Find device infos by tenantId, customerId, deviceProfileId and page link. - * - * @param tenantId the tenantId - * @param customerId the customerId - * @param deviceProfileId the deviceProfileId - * @param pageLink the page link - * @return the list of device info objects - */ - PageData findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(UUID tenantId, UUID customerId, UUID deviceProfileId, PageLink pageLink); - /** * Find devices by tenantId, customerId and devices Ids. * @@ -277,5 +217,5 @@ public interface DeviceDao extends Dao, TenantEntityDao, ExportableEntit PageData findDeviceIdInfos(PageLink pageLink); - + PageData findDeviceInfosByFilter(DeviceInfoFilter filter, PageLink pageLink); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index b9bcd83e93..a662f50dca 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -30,6 +30,7 @@ import org.thingsboard.server.cache.device.DeviceCacheKey; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceIdInfo; import org.thingsboard.server.common.data.DeviceInfo; +import org.thingsboard.server.common.data.DeviceInfoFilter; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.DeviceProfileType; import org.thingsboard.server.common.data.DeviceTransportType; @@ -69,6 +70,7 @@ import org.thingsboard.server.dao.entity.AbstractCachedEntityService; import org.thingsboard.server.dao.entity.EntityCountService; import org.thingsboard.server.dao.event.EventService; import org.thingsboard.server.dao.exception.DataValidationException; +import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; @@ -342,12 +344,17 @@ public class DeviceServiceImpl extends AbstractCachedEntityService findDeviceInfosByTenantId(TenantId tenantId, PageLink pageLink) { - log.trace("Executing findDeviceInfosByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + public PageData findDeviceInfosByFilter(DeviceInfoFilter filter, PageLink pageLink) { + log.trace("Executing findDeviceInfosByFilter, filter [{}], pageLink [{}]", filter, pageLink); + if (filter == null) { + throw new IncorrectParameterException("Filter is empty!"); + } + validateId(filter.getTenantId(), INCORRECT_TENANT_ID + filter.getTenantId()); validatePageLink(pageLink); - return deviceDao.findDeviceInfosByTenantId(tenantId.getId(), pageLink); + return deviceDao.findDeviceInfosByFilter(filter, pageLink); + } @Override @@ -387,24 +394,6 @@ public class DeviceServiceImpl extends AbstractCachedEntityService findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink) { - log.trace("Executing findDeviceInfosByTenantIdAndType, tenantId [{}], type [{}], pageLink [{}]", tenantId, type, pageLink); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - validateString(type, "Incorrect type " + type); - validatePageLink(pageLink); - return deviceDao.findDeviceInfosByTenantIdAndType(tenantId.getId(), type, pageLink); - } - - @Override - public PageData findDeviceInfosByTenantIdAndDeviceProfileId(TenantId tenantId, DeviceProfileId deviceProfileId, PageLink pageLink) { - log.trace("Executing findDeviceInfosByTenantIdAndDeviceProfileId, tenantId [{}], deviceProfileId [{}], pageLink [{}]", tenantId, deviceProfileId, pageLink); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId); - validatePageLink(pageLink); - return deviceDao.findDeviceInfosByTenantIdAndDeviceProfileId(tenantId.getId(), deviceProfileId.getId(), pageLink); - } - @Override public ListenableFuture> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List deviceIds) { log.trace("Executing findDevicesByTenantIdAndIdsAsync, tenantId [{}], deviceIds [{}]", tenantId, deviceIds); @@ -444,15 +433,6 @@ public class DeviceServiceImpl extends AbstractCachedEntityService findDeviceInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink) { - log.trace("Executing findDeviceInfosByTenantIdAndCustomerId, tenantId [{}], customerId [{}], pageLink [{}]", tenantId, customerId, pageLink); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); - validatePageLink(pageLink); - return deviceDao.findDeviceInfosByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); - } - @Override public PageData findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink) { log.trace("Executing findDevicesByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}], type [{}], pageLink [{}]", tenantId, customerId, type, pageLink); @@ -463,26 +443,6 @@ public class DeviceServiceImpl extends AbstractCachedEntityService findDeviceInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink) { - log.trace("Executing findDeviceInfosByTenantIdAndCustomerIdAndType, tenantId [{}], customerId [{}], type [{}], pageLink [{}]", tenantId, customerId, type, pageLink); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); - validateString(type, "Incorrect type " + type); - validatePageLink(pageLink); - return deviceDao.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId.getId(), customerId.getId(), type, pageLink); - } - - @Override - public PageData findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(TenantId tenantId, CustomerId customerId, DeviceProfileId deviceProfileId, PageLink pageLink) { - log.trace("Executing findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId, tenantId [{}], customerId [{}], deviceProfileId [{}], pageLink [{}]", tenantId, customerId, deviceProfileId, pageLink); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); - validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId); - validatePageLink(pageLink); - return deviceDao.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(tenantId.getId(), customerId.getId(), deviceProfileId.getId(), pageLink); - } - @Override public ListenableFuture> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List deviceIds) { log.trace("Executing findDevicesByTenantIdCustomerIdAndIdsAsync, tenantId [{}], customerId [{}], deviceIds [{}]", tenantId, customerId, deviceIds); diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index bcbed91d2a..41d6685fd8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -169,6 +169,12 @@ public class ModelConstants { public static final String DEVICE_FIRMWARE_ID_PROPERTY = "firmware_id"; public static final String DEVICE_SOFTWARE_ID_PROPERTY = "software_id"; + public static final String DEVICE_CUSTOMER_TITLE_PROPERTY = "customer_title"; + public static final String DEVICE_CUSTOMER_IS_PUBLIC_PROPERTY = "customer_is_public"; + public static final String DEVICE_DEVICE_PROFILE_NAME_PROPERTY = "device_profile_name"; + public static final String DEVICE_ATTR_ACTIVE_PROPERTY = "attribute_active"; + public static final String DEVICE_TS_ACTIVE_PROPERTY = "ts_active"; + public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text"; public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text"; @@ -176,6 +182,8 @@ public class ModelConstants { public static final String DEVICE_BY_TENANT_AND_NAME_VIEW_NAME = "device_by_tenant_and_name"; public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant"; + public static final String DEVICE_INFO_VIEW_COLUMN_FAMILY_NAME = "device_info_view"; + /** * Device profile constants. */ diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ToData.java b/dao/src/main/java/org/thingsboard/server/dao/model/ToData.java index 3c3e5ac8c4..0e69506660 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ToData.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ToData.java @@ -28,4 +28,8 @@ public interface ToData { * @return the dto object */ T toData(); + + default T toData(Object... params) { + return toData(); + } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java index ea2d27bf4b..40dba47048 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceInfoEntity.java @@ -15,48 +15,57 @@ */ package org.thingsboard.server.dao.model.sql; -import com.fasterxml.jackson.databind.JsonNode; import lombok.Data; import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Immutable; import org.thingsboard.server.common.data.DeviceInfo; +import org.thingsboard.server.dao.model.ModelConstants; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; import java.util.HashMap; import java.util.Map; @Data @EqualsAndHashCode(callSuper = true) +@Entity +@Immutable +@Table(name = ModelConstants.DEVICE_INFO_VIEW_COLUMN_FAMILY_NAME) public class DeviceInfoEntity extends AbstractDeviceEntity { - public static final Map deviceInfoColumnMap = new HashMap<>(); + public static final Map attrActiveColumnMap = new HashMap<>(); + public static final Map tsActiveColumnMap = new HashMap<>(); static { - deviceInfoColumnMap.put("customerTitle", "c.title"); - deviceInfoColumnMap.put("deviceProfileName", "p.name"); + attrActiveColumnMap.put("active", "attributeActive"); + tsActiveColumnMap.put("active", "tsActive"); } + @Column(name = ModelConstants.DEVICE_CUSTOMER_TITLE_PROPERTY) private String customerTitle; - private boolean customerIsPublic; + @Column(name = ModelConstants.DEVICE_CUSTOMER_IS_PUBLIC_PROPERTY) + private Boolean customerIsPublic; + @Column(name = ModelConstants.DEVICE_DEVICE_PROFILE_NAME_PROPERTY) private String deviceProfileName; + @Column(name = ModelConstants.DEVICE_ATTR_ACTIVE_PROPERTY) + private Boolean attributeActive; + @Column(name = ModelConstants.DEVICE_TS_ACTIVE_PROPERTY) + private Boolean tsActive; public DeviceInfoEntity() { super(); } - public DeviceInfoEntity(DeviceEntity deviceEntity, - String customerTitle, - Object customerAdditionalInfo, - String deviceProfileName) { - super(deviceEntity); - this.customerTitle = customerTitle; - if (customerAdditionalInfo != null && ((JsonNode)customerAdditionalInfo).has("isPublic")) { - this.customerIsPublic = ((JsonNode)customerAdditionalInfo).get("isPublic").asBoolean(); - } else { - this.customerIsPublic = false; - } - this.deviceProfileName = deviceProfileName; - } @Override public DeviceInfo toData() { - return new DeviceInfo(super.toDevice(), customerTitle, customerIsPublic, deviceProfileName); + return toData(false); + } + + @Override + public DeviceInfo toData(Object... persistToTelemetry) { + boolean attr = persistToTelemetry.length == 0 || !(Boolean) persistToTelemetry[0]; + return new DeviceInfo(super.toDevice(), customerTitle, Boolean.TRUE.equals(customerIsPublic), deviceProfileName, + attr ? Boolean.TRUE.equals(attributeActive) : Boolean.TRUE.equals(tsActive)); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index 98d607735e..93c079360c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -137,10 +137,6 @@ public class JpaAlarmDao extends JpaAbstractDao implements A log.trace("Try to find alarms by entity [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getStatus(), query.getPageLink()); EntityId affectedEntity = query.getAffectedEntityId(); AlarmStatusFilter asf = AlarmStatusFilter.from(query); - String assigneeId = null; - if (query.getAssigneeId() != null) { - assigneeId = query.getAssigneeId().toString(); - } if (affectedEntity != null) { return DaoUtil.toPageData( alarmRepository.findAlarms( @@ -153,7 +149,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - assigneeId, + DaoUtil.getStringId(query.getAssigneeId()), Objects.toString(query.getPageLink().getTextSearch(), ""), DaoUtil.toPageable(query.getPageLink()) ) @@ -168,7 +164,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - assigneeId, + DaoUtil.getStringId(query.getAssigneeId()), Objects.toString(query.getPageLink().getTextSearch(), ""), DaoUtil.toPageable(query.getPageLink()) ) @@ -180,10 +176,6 @@ public class JpaAlarmDao extends JpaAbstractDao implements A public PageData findCustomerAlarms(TenantId tenantId, CustomerId customerId, AlarmQuery query) { log.trace("Try to find customer alarms by status [{}] and pageLink [{}]", query.getStatus(), query.getPageLink()); AlarmStatusFilter asf = AlarmStatusFilter.from(query); - String assigneeId = null; - if (query.getAssigneeId() != null) { - assigneeId = query.getAssigneeId().toString(); - } return DaoUtil.toPageData( alarmRepository.findCustomerAlarms( tenantId.getId(), @@ -194,7 +186,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - assigneeId, + DaoUtil.getStringId(query.getAssigneeId()), Objects.toString(query.getPageLink().getTextSearch(), ""), DaoUtil.toPageable(query.getPageLink()) ) @@ -208,10 +200,6 @@ public class JpaAlarmDao extends JpaAbstractDao implements A List typeList = query.getTypeList() != null && !query.getTypeList().isEmpty() ? query.getTypeList() : null; List severityList = query.getSeverityList() != null && !query.getSeverityList().isEmpty() ? query.getSeverityList() : null; AlarmStatusFilter asf = AlarmStatusFilter.from(query.getStatusList()); - String assigneeId = null; - if (query.getAssigneeId() != null) { - assigneeId = query.getAssigneeId().toString(); - } if (affectedEntity != null) { return DaoUtil.toPageData( alarmRepository.findAlarmsV2( @@ -226,7 +214,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - assigneeId, + DaoUtil.getStringId(query.getAssigneeId()), Objects.toString(query.getPageLink().getTextSearch(), ""), DaoUtil.toPageable(query.getPageLink()) ) @@ -243,7 +231,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - assigneeId, + DaoUtil.getStringId(query.getAssigneeId()), Objects.toString(query.getPageLink().getTextSearch(), ""), DaoUtil.toPageable(query.getPageLink()) ) @@ -257,10 +245,6 @@ public class JpaAlarmDao extends JpaAbstractDao implements A List typeList = query.getTypeList() != null && !query.getTypeList().isEmpty() ? query.getTypeList() : null; List severityList = query.getSeverityList() != null && !query.getSeverityList().isEmpty() ? query.getSeverityList() : null; AlarmStatusFilter asf = AlarmStatusFilter.from(query.getStatusList()); - String assigneeId = null; - if (query.getAssigneeId() != null) { - assigneeId = query.getAssigneeId().toString(); - } return DaoUtil.toPageData( alarmRepository.findCustomerAlarmsV2( tenantId.getId(), @@ -273,7 +257,7 @@ public class JpaAlarmDao extends JpaAbstractDao implements A asf.hasClearFilter() && asf.getClearFilter(), asf.hasAckFilter(), asf.hasAckFilter() && asf.getAckFilter(), - assigneeId, + DaoUtil.getStringId(query.getAssigneeId()), Objects.toString(query.getPageLink().getTextSearch(), ""), DaoUtil.toPageable(query.getPageLink()) ) diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java index cf711e43a0..ac411a580b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java @@ -22,6 +22,9 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.DeviceIdInfo; +import org.thingsboard.server.common.data.id.CustomerId; +import org.thingsboard.server.common.data.id.DeviceProfileId; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.ExportableEntityRepository; import org.thingsboard.server.dao.model.sql.DeviceEntity; import org.thingsboard.server.dao.model.sql.DeviceInfoEntity; @@ -29,16 +32,9 @@ import org.thingsboard.server.dao.model.sql.DeviceInfoEntity; import java.util.List; import java.util.UUID; -/** - * Created by Valerii Sosliuk on 5/6/2017. - */ public interface DeviceRepository extends JpaRepository, ExportableEntityRepository { - @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + - "FROM DeviceEntity d " + - "LEFT JOIN CustomerEntity c on c.id = d.customerId " + - "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + - "WHERE d.id = :deviceId") + @Query("SELECT d FROM DeviceInfoEntity d WHERE d.id = :deviceId") DeviceInfoEntity findDeviceInfoById(@Param("deviceId") UUID deviceId); @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + @@ -57,10 +53,7 @@ public interface DeviceRepository extends JpaRepository, Exp @Param("searchText") String searchText, Pageable pageable); - @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + - "FROM DeviceEntity d " + - "LEFT JOIN CustomerEntity c on c.id = d.customerId " + - "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + + @Query("SELECT d FROM DeviceInfoEntity d " + "WHERE d.tenantId = :tenantId " + "AND d.customerId = :customerId " + "AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :searchText, '%'))") @@ -79,19 +72,6 @@ public interface DeviceRepository extends JpaRepository, Exp @Param("textSearch") String textSearch, Pageable pageable); - @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + - "FROM DeviceEntity d " + - "LEFT JOIN CustomerEntity c on c.id = d.customerId " + - "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + - "WHERE d.tenantId = :tenantId " + - "AND (LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + - "OR LOWER(d.label) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + - "OR LOWER(p.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + - "OR LOWER(c.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')))") - Page findDeviceInfosByTenantId(@Param("tenantId") UUID tenantId, - @Param("textSearch") String textSearch, - Pageable pageable); - @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + "AND d.type = :type " + "AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") @@ -105,9 +85,9 @@ public interface DeviceRepository extends JpaRepository, Exp "AND d.firmwareId = null " + "AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") Page findByTenantIdAndTypeAndFirmwareIdIsNull(@Param("tenantId") UUID tenantId, - @Param("deviceProfileId") UUID deviceProfileId, - @Param("textSearch") String textSearch, - Pageable pageable); + @Param("deviceProfileId") UUID deviceProfileId, + @Param("textSearch") String textSearch, + Pageable pageable); @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + "AND d.deviceProfileId = :deviceProfileId " + @@ -130,34 +110,6 @@ public interface DeviceRepository extends JpaRepository, Exp Long countByTenantIdAndDeviceProfileIdAndSoftwareIdIsNull(@Param("tenantId") UUID tenantId, @Param("deviceProfileId") UUID deviceProfileId); - @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + - "FROM DeviceEntity d " + - "LEFT JOIN CustomerEntity c on c.id = d.customerId " + - "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + - "WHERE d.tenantId = :tenantId " + - "AND d.type = :type " + - "AND (LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + - "OR LOWER(d.label) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + - "OR LOWER(c.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')))") - Page findDeviceInfosByTenantIdAndType(@Param("tenantId") UUID tenantId, - @Param("type") String type, - @Param("textSearch") String textSearch, - Pageable pageable); - - @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + - "FROM DeviceEntity d " + - "LEFT JOIN CustomerEntity c on c.id = d.customerId " + - "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + - "WHERE d.tenantId = :tenantId " + - "AND d.deviceProfileId = :deviceProfileId " + - "AND (LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + - "OR LOWER(d.label) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + - "OR LOWER(c.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')))") - Page findDeviceInfosByTenantIdAndDeviceProfileId(@Param("tenantId") UUID tenantId, - @Param("deviceProfileId") UUID deviceProfileId, - @Param("textSearch") String textSearch, - Pageable pageable); - @Query("SELECT d FROM DeviceEntity d WHERE d.tenantId = :tenantId " + "AND d.customerId = :customerId " + "AND d.type = :type " + @@ -168,33 +120,25 @@ public interface DeviceRepository extends JpaRepository, Exp @Param("textSearch") String textSearch, Pageable pageable); - @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + - "FROM DeviceEntity d " + - "LEFT JOIN CustomerEntity c on c.id = d.customerId " + - "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + + @Query("SELECT d FROM DeviceInfoEntity d " + "WHERE d.tenantId = :tenantId " + - "AND d.customerId = :customerId " + - "AND d.type = :type " + - "AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") - Page findDeviceInfosByTenantIdAndCustomerIdAndType(@Param("tenantId") UUID tenantId, - @Param("customerId") UUID customerId, - @Param("type") String type, - @Param("textSearch") String textSearch, - Pageable pageable); - - @Query("SELECT new org.thingsboard.server.dao.model.sql.DeviceInfoEntity(d, c.title, c.additionalInfo, p.name) " + - "FROM DeviceEntity d " + - "LEFT JOIN CustomerEntity c on c.id = d.customerId " + - "LEFT JOIN DeviceProfileEntity p on p.id = d.deviceProfileId " + - "WHERE d.tenantId = :tenantId " + - "AND d.customerId = :customerId " + - "AND d.deviceProfileId = :deviceProfileId " + - "AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") - Page findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(@Param("tenantId") UUID tenantId, - @Param("customerId") UUID customerId, - @Param("deviceProfileId") UUID deviceProfileId, - @Param("textSearch") String textSearch, - Pageable pageable); + "AND (:customerId IS NULL OR d.customerId = uuid(:customerId)) " + + "AND ((:deviceType) IS NULL OR d.type = :deviceType) " + + "AND (:deviceProfileId IS NULL OR d.deviceProfileId = uuid(:deviceProfileId)) " + + "AND ((:filterByActive) IS FALSE OR (((:persistToTelemetry) IS TRUE AND d.tsActive = :deviceActive) OR ((:persistToTelemetry) IS FALSE AND d.attributeActive = :deviceActive))) " + + "AND (LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + + "OR LOWER(d.label) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + + "OR LOWER(d.type) LIKE LOWER(CONCAT('%', :textSearch, '%')) " + + "OR LOWER(d.customerTitle) LIKE LOWER(CONCAT('%', :textSearch, '%')))") + Page findDeviceInfosByFilter(@Param("tenantId") UUID tenantId, + @Param("customerId") String customerId, + @Param("deviceType") String type, + @Param("deviceProfileId") String deviceProfileId, + @Param("filterByActive") boolean filterByActive, + @Param("persistToTelemetry") boolean persistToTelemetry, + @Param("deviceActive") boolean active, + @Param("textSearch") String textSearch, + Pageable pageable); @Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId") List findTenantDeviceTypes(@Param("tenantId") UUID tenantId); @@ -237,10 +181,10 @@ public interface DeviceRepository extends JpaRepository, Exp *

* There is two way to count devices. * OPTIMAL: count(*) - * - returns _row_count_ and use index-only scan (super fast). + * - returns _row_count_ and use index-only scan (super fast). * SLOW: count(id) - * - returns _NON_NULL_id_count and performs table scan to verify isNull for each id in filtered rows. - * */ + * - returns _NON_NULL_id_count and performs table scan to verify isNull for each id in filtered rows. + */ @Query("SELECT count(*) FROM DeviceEntity d WHERE d.tenantId = :tenantId") Long countByTenantId(@Param("tenantId") UUID tenantId); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index a16245ee45..5a244cbd94 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -16,8 +16,11 @@ package org.thingsboard.server.dao.sql.device; import com.google.common.util.concurrent.ListenableFuture; +import lombok.Getter; +import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -26,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceIdInfo; import org.thingsboard.server.common.data.DeviceInfo; +import org.thingsboard.server.common.data.DeviceInfoFilter; import org.thingsboard.server.common.data.DeviceTransportType; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; @@ -43,9 +47,11 @@ import org.thingsboard.server.dao.model.sql.DeviceInfoEntity; import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import org.thingsboard.server.dao.util.SqlDao; +import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -58,6 +64,11 @@ import java.util.UUID; @Slf4j public class JpaDeviceDao extends JpaAbstractSearchTextDao implements DeviceDao { + @Value("${state.persistToTelemetry:false}") + private boolean persistToTelemetry; + + private Map activeColumnMap; + @Autowired private DeviceRepository deviceRepository; @@ -74,9 +85,14 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao return deviceRepository; } + @PostConstruct + public void init() { + activeColumnMap = persistToTelemetry ? DeviceInfoEntity.tsActiveColumnMap : DeviceInfoEntity.attrActiveColumnMap; + } + @Override public DeviceInfo findDeviceInfoById(TenantId tenantId, UUID deviceId) { - return DaoUtil.getData(deviceRepository.findDeviceInfoById(deviceId)); + return DaoUtil.getData(deviceRepository.findDeviceInfoById(deviceId), persistToTelemetry); } @Override @@ -104,12 +120,18 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao } @Override - public PageData findDeviceInfosByTenantId(UUID tenantId, PageLink pageLink) { + public PageData findDeviceInfosByFilter(DeviceInfoFilter filter, PageLink pageLink) { return DaoUtil.toPageData( - deviceRepository.findDeviceInfosByTenantId( - tenantId, + deviceRepository.findDeviceInfosByFilter( + filter.getTenantId().getId(), + DaoUtil.getStringId(filter.getCustomerId()), + filter.getType(), + DaoUtil.getStringId(filter.getDeviceProfileId()), + filter.getActive() != null, + persistToTelemetry, + Boolean.TRUE.equals(filter.getActive()), Objects.toString(pageLink.getTextSearch(), ""), - DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); + DaoUtil.toPageable(pageLink, activeColumnMap)), persistToTelemetry); } @Override @@ -152,16 +174,6 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao return DaoUtil.pageToPageData(deviceRepository.findIdsByDeviceProfileTransportType(transportType, DaoUtil.toPageable(pageLink))); } - @Override - public PageData findDeviceInfosByTenantIdAndCustomerId(UUID tenantId, UUID customerId, PageLink pageLink) { - return DaoUtil.toPageData( - deviceRepository.findDeviceInfosByTenantIdAndCustomerId( - tenantId, - customerId, - Objects.toString(pageLink.getTextSearch(), ""), - DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); - } - @Override public ListenableFuture> findDevicesByTenantIdCustomerIdAndIdsAsync(UUID tenantId, UUID customerId, List deviceIds) { return service.submit(() -> DaoUtil.convertDataList( @@ -208,26 +220,6 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao ); } - @Override - public PageData findDeviceInfosByTenantIdAndType(UUID tenantId, String type, PageLink pageLink) { - return DaoUtil.toPageData( - deviceRepository.findDeviceInfosByTenantIdAndType( - tenantId, - type, - Objects.toString(pageLink.getTextSearch(), ""), - DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); - } - - @Override - public PageData findDeviceInfosByTenantIdAndDeviceProfileId(UUID tenantId, UUID deviceProfileId, PageLink pageLink) { - return DaoUtil.toPageData( - deviceRepository.findDeviceInfosByTenantIdAndDeviceProfileId( - tenantId, - deviceProfileId, - Objects.toString(pageLink.getTextSearch(), ""), - DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); - } - @Override public PageData findDevicesByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { return DaoUtil.toPageData( @@ -239,28 +231,6 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao DaoUtil.toPageable(pageLink))); } - @Override - public PageData findDeviceInfosByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, PageLink pageLink) { - return DaoUtil.toPageData( - deviceRepository.findDeviceInfosByTenantIdAndCustomerIdAndType( - tenantId, - customerId, - type, - Objects.toString(pageLink.getTextSearch(), ""), - DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); - } - - @Override - public PageData findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId(UUID tenantId, UUID customerId, UUID deviceProfileId, PageLink pageLink) { - return DaoUtil.toPageData( - deviceRepository.findDeviceInfosByTenantIdAndCustomerIdAndDeviceProfileId( - tenantId, - customerId, - deviceProfileId, - Objects.toString(pageLink.getTextSearch(), ""), - DaoUtil.toPageable(pageLink, DeviceInfoEntity.deviceInfoColumnMap))); - } - @Override public ListenableFuture> findTenantDeviceTypesAsync(UUID tenantId) { return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(tenantId))); diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index c22feb0695..b8073213cb 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -859,6 +859,16 @@ CREATE TABLE IF NOT EXISTS user_settings ( CONSTRAINT user_settings_pkey PRIMARY KEY (user_id, type) ); +CREATE OR REPLACE VIEW device_info_view as +SELECT d.* + , c.title as customer_title + , c.additional_info::json->>'isPublic' as customer_is_public + , d.type as device_profile_name + , (select bool_v from attribute_kv da where da.entity_id = d.id and da.attribute_key = 'active') as attribute_active + , (select bool_v from ts_kv_latest dt where dt.entity_id = d.id and dt.key = (select key_id from ts_kv_dictionary where key = 'active')) as ts_active +FROM device d + LEFT JOIN customer c ON c.id = d.customer_id; + DROP VIEW IF EXISTS alarm_info CASCADE; CREATE VIEW alarm_info AS SELECT a.*, diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java index 73b71ceae3..cb46e27c81 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java @@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceInfo; +import org.thingsboard.server.common.data.DeviceInfoFilter; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.OtaPackage; @@ -446,7 +447,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); device.setName(name); device.setType("default"); - devicesTitle1.add(new DeviceInfo(deviceService.saveDevice(device), null, false, "default")); + devicesTitle1.add(new DeviceInfo(deviceService.saveDevice(device), null, false, "default", false)); } String title2 = "Device title 2"; List devicesTitle2 = new ArrayList<>(); @@ -458,14 +459,14 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { name = i % 2 == 0 ? name.toLowerCase() : name.toUpperCase(); device.setName(name); device.setType("default"); - devicesTitle2.add(new DeviceInfo(deviceService.saveDevice(device), null, false, "default")); + devicesTitle2.add(new DeviceInfo(deviceService.saveDevice(device), null, false, "default", false)); } List loadedDevicesTitle1 = new ArrayList<>(); PageLink pageLink = new PageLink(15, 0, title1); PageData pageData = null; do { - pageData = deviceService.findDeviceInfosByTenantId(tenantId, pageLink); + pageData = deviceService.findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).build(), pageLink); loadedDevicesTitle1.addAll(pageData.getData()); if (pageData.hasNext()) { pageLink = pageLink.nextPageLink(); @@ -480,7 +481,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { List loadedDevicesTitle2 = new ArrayList<>(); pageLink = new PageLink(4, 0, title2); do { - pageData = deviceService.findDeviceInfosByTenantId(tenantId, pageLink); + pageData = deviceService.findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).build(), pageLink); loadedDevicesTitle2.addAll(pageData.getData()); if (pageData.hasNext()) { pageLink = pageLink.nextPageLink(); @@ -497,7 +498,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { } pageLink = new PageLink(4, 0, title1); - pageData = deviceService.findDeviceInfosByTenantId(tenantId, pageLink); + pageData = deviceService.findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).build(), pageLink); Assert.assertFalse(pageData.hasNext()); Assert.assertEquals(0, pageData.getData().size()); @@ -506,7 +507,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { } pageLink = new PageLink(4, 0, title2); - pageData = deviceService.findDeviceInfosByTenantId(tenantId, pageLink); + pageData = deviceService.findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).build(), pageLink); Assert.assertFalse(pageData.hasNext()); Assert.assertEquals(0, pageData.getData().size()); } @@ -605,14 +606,14 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { device.setName("Device" + i); device.setType("default"); device = deviceService.saveDevice(device); - devices.add(new DeviceInfo(deviceService.assignDeviceToCustomer(tenantId, device.getId(), customerId), customer.getTitle(), customer.isPublic(), "default")); + devices.add(new DeviceInfo(deviceService.assignDeviceToCustomer(tenantId, device.getId(), customerId), customer.getTitle(), customer.isPublic(), "default", false)); } List loadedDevices = new ArrayList<>(); PageLink pageLink = new PageLink(23); PageData pageData = null; do { - pageData = deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink); + pageData = deviceService.findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).customerId(customerId).build(), pageLink); loadedDevices.addAll(pageData.getData()); if (pageData.hasNext()) { pageLink = pageLink.nextPageLink(); @@ -627,7 +628,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { deviceService.unassignCustomerDevices(tenantId, customerId); pageLink = new PageLink(33); - pageData = deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink); + pageData = deviceService.findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).customerId(customerId).build(), pageLink); Assert.assertFalse(pageData.hasNext()); Assert.assertTrue(pageData.getData().isEmpty()); } @@ -848,7 +849,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { PageLink pageLinkWithLabel = new PageLink(100, 0, "label"); List deviceInfosWithLabel = deviceService - .findDeviceInfosByTenantId(tenantId, pageLinkWithLabel).getData(); + .findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).build(), pageLinkWithLabel).getData(); Assert.assertFalse(deviceInfosWithLabel.isEmpty()); Assert.assertTrue( @@ -862,7 +863,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { PageLink pageLinkWithCustomer = new PageLink(100, 0, savedCustomer.getSearchText()); List deviceInfosWithCustomer = deviceService - .findDeviceInfosByTenantId(tenantId, pageLinkWithCustomer).getData(); + .findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).build(), pageLinkWithCustomer).getData(); Assert.assertFalse(deviceInfosWithCustomer.isEmpty()); Assert.assertTrue( @@ -877,7 +878,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { PageLink pageLinkWithType = new PageLink(100, 0, device.getType()); List deviceInfosWithType = deviceService - .findDeviceInfosByTenantId(tenantId, pageLinkWithType).getData(); + .findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).build(), pageLinkWithType).getData(); Assert.assertFalse(deviceInfosWithType.isEmpty()); Assert.assertTrue( @@ -907,7 +908,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { PageLink pageLinkWithLabel = new PageLink(100, 0, "label"); List deviceInfosWithLabel = deviceService - .findDeviceInfosByTenantIdAndType(tenantId, device.getType(), pageLinkWithLabel).getData(); + .findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).type(device.getType()).build(), pageLinkWithLabel).getData(); Assert.assertFalse(deviceInfosWithLabel.isEmpty()); Assert.assertTrue( @@ -922,7 +923,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { PageLink pageLinkWithCustomer = new PageLink(100, 0, savedCustomer.getSearchText()); List deviceInfosWithCustomer = deviceService - .findDeviceInfosByTenantIdAndType(tenantId, device.getType(), pageLinkWithCustomer).getData(); + .findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).type(device.getType()).build(), pageLinkWithCustomer).getData(); Assert.assertFalse(deviceInfosWithCustomer.isEmpty()); Assert.assertTrue( @@ -953,7 +954,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { PageLink pageLinkWithLabel = new PageLink(100, 0, "label"); List deviceInfosWithLabel = deviceService - .findDeviceInfosByTenantIdAndDeviceProfileId(tenantId, savedDevice.getDeviceProfileId(), pageLinkWithLabel).getData(); + .findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).deviceProfileId(savedDevice.getDeviceProfileId()).build(), pageLinkWithLabel).getData(); Assert.assertFalse(deviceInfosWithLabel.isEmpty()); Assert.assertTrue( @@ -968,7 +969,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { PageLink pageLinkWithCustomer = new PageLink(100, 0, savedCustomer.getSearchText()); List deviceInfosWithCustomer = deviceService - .findDeviceInfosByTenantIdAndDeviceProfileId(tenantId, savedDevice.getDeviceProfileId(), pageLinkWithCustomer).getData(); + .findDeviceInfosByFilter(DeviceInfoFilter.builder().tenantId(tenantId).deviceProfileId(savedDevice.getDeviceProfileId()).build(), pageLinkWithCustomer).getData(); Assert.assertFalse(deviceInfosWithCustomer.isEmpty()); Assert.assertTrue(