Device info view improvements
This commit is contained in:
parent
dcbc4c5c7d
commit
9e589c8044
@ -16,16 +16,27 @@
|
||||
|
||||
-- DEVICE INFO VIEW START
|
||||
|
||||
DROP VIEW IF EXISTS device_info_view CASCADE;
|
||||
CREATE OR REPLACE VIEW device_info_view as
|
||||
DROP VIEW IF EXISTS device_info_active_attribute_view CASCADE;
|
||||
CREATE OR REPLACE VIEW device_info_active_attribute_view AS
|
||||
SELECT d.*
|
||||
, c.title as customer_title
|
||||
, c.additional_info::json->>'isPublic' as customer_is_public
|
||||
, COALESCE((c.additional_info::json->>'isPublic')::bool, FALSE) 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
|
||||
, COALESCE(da.bool_v, FALSE) as active
|
||||
FROM device d
|
||||
LEFT JOIN customer c ON c.id = d.customer_id;
|
||||
LEFT JOIN customer c ON c.id = d.customer_id
|
||||
LEFT JOIN attribute_kv da ON da.entity_id = d.id and da.attribute_key = 'active';
|
||||
|
||||
DROP VIEW IF EXISTS device_info_active_ts_view CASCADE;
|
||||
CREATE OR REPLACE VIEW device_info_active_ts_view AS
|
||||
SELECT d.*
|
||||
, c.title as customer_title
|
||||
, COALESCE((c.additional_info::json->>'isPublic')::bool, FALSE) as customer_is_public
|
||||
, d.type as device_profile_name
|
||||
, COALESCE(dt.bool_v, FALSE) as active
|
||||
FROM device d
|
||||
LEFT JOIN customer c ON c.id = d.customer_id
|
||||
LEFT JOIN ts_kv_latest dt ON dt.entity_id = d.id and dt.key = (select key_id from ts_kv_dictionary where key = 'active');
|
||||
|
||||
-- DEVICE INFO VIEW END
|
||||
|
||||
|
||||
@ -53,6 +53,9 @@ public class ThingsboardInstallService {
|
||||
@Value("${install.load_demo:false}")
|
||||
private Boolean loadDemo;
|
||||
|
||||
@Value("${state.persistToTelemetry:false}")
|
||||
private boolean persistToTelemetry;
|
||||
|
||||
@Autowired
|
||||
private EntityDatabaseSchemaService entityDatabaseSchemaService;
|
||||
|
||||
@ -247,6 +250,7 @@ public class ThingsboardInstallService {
|
||||
case "3.4.4":
|
||||
log.info("Upgrading ThingsBoard from version 3.4.4 to 3.5.0 ...");
|
||||
databaseEntitiesUpgradeService.upgradeDatabase("3.4.4");
|
||||
entityDatabaseSchemaService.createOrUpdateDeviceInfoView(persistToTelemetry);
|
||||
log.info("Updating system data...");
|
||||
systemDataLoaderService.updateSystemWidgets();
|
||||
if (!getEnv("SKIP_DEFAULT_NOTIFICATION_CONFIGS_CREATION", false)) {
|
||||
@ -272,6 +276,8 @@ public class ThingsboardInstallService {
|
||||
|
||||
entityDatabaseSchemaService.createDatabaseSchema();
|
||||
|
||||
entityDatabaseSchemaService.createOrUpdateDeviceInfoView(persistToTelemetry);
|
||||
|
||||
log.info("Installing DataBase schema for timeseries...");
|
||||
|
||||
if (noSqlKeyspaceService != null) {
|
||||
|
||||
@ -16,4 +16,7 @@
|
||||
package org.thingsboard.server.service.install;
|
||||
|
||||
public interface EntityDatabaseSchemaService extends DatabaseSchemaService {
|
||||
|
||||
void createOrUpdateDeviceInfoView(boolean activityStateInTelemetry);
|
||||
|
||||
}
|
||||
|
||||
@ -39,4 +39,10 @@ public class SqlEntityDatabaseSchemaService extends SqlAbstractDatabaseSchemaSer
|
||||
executeQueryFromFile(SCHEMA_ENTITIES_IDX_PSQL_ADDON_SQL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createOrUpdateDeviceInfoView(boolean activityStateInTelemetry) {
|
||||
String sourceViewName = activityStateInTelemetry ? "device_info_active_ts_view" : "device_info_active_attribute_view";
|
||||
executeQuery("DROP VIEW IF EXISTS device_info_view CASCADE;");
|
||||
executeQuery("CREATE OR REPLACE VIEW device_info_view AS SELECT * FROM " + sourceViewName + ";");
|
||||
}
|
||||
}
|
||||
|
||||
@ -645,6 +645,10 @@ state:
|
||||
# Should be greater then transport.sessions.report_timeout
|
||||
defaultInactivityTimeoutInSec: "${DEFAULT_INACTIVITY_TIMEOUT:600}"
|
||||
defaultStateCheckIntervalInSec: "${DEFAULT_STATE_CHECK_INTERVAL:60}"
|
||||
# Controls whether we store device 'active' flag in attributes (default) or telemetry.
|
||||
# If you device to change this parameter, you should re-create the device info view as one of the following:
|
||||
# If 'persistToTelemetry' is changed from 'false' to 'true': 'CREATE OR REPLACE VIEW device_info_view AS SELECT * FROM device_info_active_ts_view;'
|
||||
# If 'persistToTelemetry' is changed from 'true' to 'false': 'CREATE OR REPLACE VIEW device_info_view AS SELECT * FROM device_info_active_attribute_view;'
|
||||
persistToTelemetry: "${PERSIST_STATE_TO_TELEMETRY:false}"
|
||||
|
||||
tbel:
|
||||
|
||||
@ -46,12 +46,6 @@ public abstract class DaoUtil {
|
||||
return new PageData<>(data, page.getTotalPages(), page.getTotalElements(), page.hasNext());
|
||||
}
|
||||
|
||||
public static <T> PageData<T> toPageData(Page<? extends ToData<T>> page, Object... params) {
|
||||
List<T> data = convertDataList(page.getContent(), params);
|
||||
return new PageData<>(data, page.getTotalPages(), page.getTotalElements(), page.hasNext());
|
||||
}
|
||||
|
||||
|
||||
public static <T> PageData<T> pageToPageData(Page<T> page) {
|
||||
return new PageData<>(page.getContent(), page.getTotalPages(), page.getTotalElements(), page.hasNext());
|
||||
}
|
||||
@ -85,19 +79,6 @@ public abstract class DaoUtil {
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> List<T> convertDataList(Collection<? extends ToData<T>> toDataList, Object... params) {
|
||||
List<T> list = Collections.emptyList();
|
||||
if (toDataList != null && !toDataList.isEmpty()) {
|
||||
list = new ArrayList<>();
|
||||
for (ToData<T> object : toDataList) {
|
||||
if (object != null) {
|
||||
list.add(object.toData(params));
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <T> T getData(ToData<T> data) {
|
||||
T object = null;
|
||||
if (data != null) {
|
||||
@ -106,15 +87,6 @@ public abstract class DaoUtil {
|
||||
return object;
|
||||
}
|
||||
|
||||
public static <T> T getData(ToData<T> data, Object... params) {
|
||||
T object = null;
|
||||
if (data != null) {
|
||||
object = data.toData(params);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
|
||||
public static <T> T getData(Optional<? extends ToData<T>> data) {
|
||||
T object = null;
|
||||
if (data.isPresent()) {
|
||||
|
||||
@ -172,8 +172,7 @@ public class ModelConstants {
|
||||
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_ACTIVE_PROPERTY = "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";
|
||||
|
||||
@ -29,7 +29,4 @@ public interface ToData<T> {
|
||||
*/
|
||||
T toData();
|
||||
|
||||
default T toData(Object... params) {
|
||||
return toData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,8 +24,6 @@ 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)
|
||||
@ -34,23 +32,14 @@ import java.util.Map;
|
||||
@Table(name = ModelConstants.DEVICE_INFO_VIEW_COLUMN_FAMILY_NAME)
|
||||
public class DeviceInfoEntity extends AbstractDeviceEntity<DeviceInfo> {
|
||||
|
||||
public static final Map<String, String> attrActiveColumnMap = new HashMap<>();
|
||||
public static final Map<String, String> tsActiveColumnMap = new HashMap<>();
|
||||
static {
|
||||
attrActiveColumnMap.put("active", "attributeActive");
|
||||
tsActiveColumnMap.put("active", "tsActive");
|
||||
}
|
||||
|
||||
@Column(name = ModelConstants.DEVICE_CUSTOMER_TITLE_PROPERTY)
|
||||
private String customerTitle;
|
||||
@Column(name = ModelConstants.DEVICE_CUSTOMER_IS_PUBLIC_PROPERTY)
|
||||
private Boolean customerIsPublic;
|
||||
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;
|
||||
@Column(name = ModelConstants.DEVICE_ACTIVE_PROPERTY)
|
||||
private boolean active;
|
||||
|
||||
public DeviceInfoEntity() {
|
||||
super();
|
||||
@ -59,13 +48,7 @@ public class DeviceInfoEntity extends AbstractDeviceEntity<DeviceInfo> {
|
||||
|
||||
@Override
|
||||
public DeviceInfo toData() {
|
||||
return toData(false);
|
||||
return new DeviceInfo(super.toDevice(), customerTitle, customerIsPublic, deviceProfileName, active);
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,10 +21,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
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;
|
||||
@ -125,7 +121,7 @@ public interface DeviceRepository extends JpaRepository<DeviceEntity, UUID>, Exp
|
||||
"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 ((:filterByActive) IS FALSE OR d.active = :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, '%')) " +
|
||||
@ -135,7 +131,6 @@ public interface DeviceRepository extends JpaRepository<DeviceEntity, UUID>, Exp
|
||||
@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);
|
||||
@ -178,7 +173,7 @@ public interface DeviceRepository extends JpaRepository<DeviceEntity, UUID>, Exp
|
||||
/**
|
||||
* Count devices by tenantId.
|
||||
* Custom query applied because default QueryDSL produces slow count(id).
|
||||
* <p>
|
||||
*
|
||||
* There is two way to count devices.
|
||||
* OPTIMAL: count(*)
|
||||
* - returns _row_count_ and use index-only scan (super fast).
|
||||
|
||||
@ -64,11 +64,6 @@ import java.util.UUID;
|
||||
@Slf4j
|
||||
public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> implements DeviceDao {
|
||||
|
||||
@Value("${state.persistToTelemetry:false}")
|
||||
private boolean persistToTelemetry;
|
||||
|
||||
private Map<String, String> activeColumnMap;
|
||||
|
||||
@Autowired
|
||||
private DeviceRepository deviceRepository;
|
||||
|
||||
@ -85,14 +80,9 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
|
||||
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), persistToTelemetry);
|
||||
return DaoUtil.getData(deviceRepository.findDeviceInfoById(deviceId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -128,10 +118,9 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
|
||||
filter.getType(),
|
||||
DaoUtil.getStringId(filter.getDeviceProfileId()),
|
||||
filter.getActive() != null,
|
||||
persistToTelemetry,
|
||||
Boolean.TRUE.equals(filter.getActive()),
|
||||
Objects.toString(pageLink.getTextSearch(), ""),
|
||||
DaoUtil.toPageable(pageLink, activeColumnMap)), persistToTelemetry);
|
||||
DaoUtil.toPageable(pageLink)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -859,15 +859,27 @@ CREATE TABLE IF NOT EXISTS user_settings (
|
||||
CONSTRAINT user_settings_pkey PRIMARY KEY (user_id, type)
|
||||
);
|
||||
|
||||
CREATE OR REPLACE VIEW device_info_view as
|
||||
DROP VIEW IF EXISTS device_info_active_attribute_view CASCADE;
|
||||
CREATE OR REPLACE VIEW device_info_active_attribute_view AS
|
||||
SELECT d.*
|
||||
, c.title as customer_title
|
||||
, c.additional_info::json->>'isPublic' as customer_is_public
|
||||
, COALESCE((c.additional_info::json->>'isPublic')::bool, FALSE) 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
|
||||
, COALESCE(da.bool_v, FALSE) as active
|
||||
FROM device d
|
||||
LEFT JOIN customer c ON c.id = d.customer_id;
|
||||
LEFT JOIN customer c ON c.id = d.customer_id
|
||||
LEFT JOIN attribute_kv da ON da.entity_id = d.id and da.attribute_key = 'active';
|
||||
|
||||
DROP VIEW IF EXISTS device_info_active_ts_view CASCADE;
|
||||
CREATE OR REPLACE VIEW device_info_active_ts_view AS
|
||||
SELECT d.*
|
||||
, c.title as customer_title
|
||||
, COALESCE((c.additional_info::json->>'isPublic')::bool, FALSE) as customer_is_public
|
||||
, d.type as device_profile_name
|
||||
, COALESCE(dt.bool_v, FALSE) as active
|
||||
FROM device d
|
||||
LEFT JOIN customer c ON c.id = d.customer_id
|
||||
LEFT JOIN ts_kv_latest dt ON dt.entity_id = d.id and dt.key = (select key_id from ts_kv_dictionary where key = 'active');
|
||||
|
||||
DROP VIEW IF EXISTS alarm_info CASCADE;
|
||||
CREATE VIEW alarm_info AS
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user