Added copy attributes to entity view rule node
This commit is contained in:
		
							parent
							
								
									8f72adfb1d
								
							
						
					
					
						commit
						020b7a4ec6
					
				@ -48,6 +48,7 @@ import org.thingsboard.server.dao.attributes.AttributesService;
 | 
			
		||||
import org.thingsboard.server.dao.audit.AuditLogService;
 | 
			
		||||
import org.thingsboard.server.dao.customer.CustomerService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceService;
 | 
			
		||||
import org.thingsboard.server.dao.entityview.EntityViewService;
 | 
			
		||||
import org.thingsboard.server.dao.event.EventService;
 | 
			
		||||
import org.thingsboard.server.dao.relation.RelationService;
 | 
			
		||||
import org.thingsboard.server.dao.rule.RuleChainService;
 | 
			
		||||
@ -159,6 +160,10 @@ public class ActorSystemContext {
 | 
			
		||||
    @Getter
 | 
			
		||||
    private AuditLogService auditLogService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    @Getter
 | 
			
		||||
    private EntityViewService entityViewService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    @Getter
 | 
			
		||||
    private TelemetrySubscriptionService tsSubService;
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,7 @@ import org.thingsboard.server.dao.asset.AssetService;
 | 
			
		||||
import org.thingsboard.server.dao.attributes.AttributesService;
 | 
			
		||||
import org.thingsboard.server.dao.customer.CustomerService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceService;
 | 
			
		||||
import org.thingsboard.server.dao.entityview.EntityViewService;
 | 
			
		||||
import org.thingsboard.server.dao.relation.RelationService;
 | 
			
		||||
import org.thingsboard.server.dao.rule.RuleChainService;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantService;
 | 
			
		||||
@ -212,6 +213,11 @@ class DefaultTbContext implements TbContext {
 | 
			
		||||
        return mainCtx.getRelationService();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public EntityViewService getEntityViewService() {
 | 
			
		||||
        return mainCtx.getEntityViewService();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public MailService getMailService() {
 | 
			
		||||
        if (mainCtx.isAllowSystemMailService()) {
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@ package org.thingsboard.server.dao.entityview;
 | 
			
		||||
 | 
			
		||||
import com.datastax.driver.core.Statement;
 | 
			
		||||
import com.datastax.driver.core.querybuilder.Select;
 | 
			
		||||
import com.google.common.util.concurrent.ListenableFuture;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
import org.thingsboard.server.common.data.EntitySubtype;
 | 
			
		||||
@ -105,4 +106,10 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao<Entit
 | 
			
		||||
    public List<EntityView> findEntityViewsByTenantIdAndCustomerIdAndEntityId(UUID tenantId, UUID customerId, UUID entityId, TextPageLink pageLink) {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(UUID tenantId, UUID entityId) {
 | 
			
		||||
        // TODO: implement this
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,8 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.dao.entityview;
 | 
			
		||||
 | 
			
		||||
import com.google.common.util.concurrent.ListenableFuture;
 | 
			
		||||
import org.thingsboard.server.common.data.Device;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
import org.thingsboard.server.common.data.page.TextPageLink;
 | 
			
		||||
import org.thingsboard.server.dao.Dao;
 | 
			
		||||
@ -91,4 +93,6 @@ public interface EntityViewDao extends Dao<EntityView> {
 | 
			
		||||
                                                                       UUID customerId,
 | 
			
		||||
                                                                       UUID entityId,
 | 
			
		||||
                                                                       TextPageLink pageLink);
 | 
			
		||||
 | 
			
		||||
    ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(UUID tenantId, UUID entityId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ import org.thingsboard.server.common.data.Device;
 | 
			
		||||
import org.thingsboard.server.common.data.EntitySubtype;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
import org.thingsboard.server.common.data.Tenant;
 | 
			
		||||
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
 | 
			
		||||
import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
 | 
			
		||||
import org.thingsboard.server.common.data.id.*;
 | 
			
		||||
@ -65,4 +66,6 @@ public interface EntityViewService {
 | 
			
		||||
    ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
 | 
			
		||||
 | 
			
		||||
    ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
 | 
			
		||||
 | 
			
		||||
    ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -25,11 +25,13 @@ import org.springframework.cache.CacheManager;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
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.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
import org.thingsboard.server.common.data.Tenant;
 | 
			
		||||
import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityViewId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
@ -52,8 +54,10 @@ import java.util.Collection;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.dao.DaoUtil.toUUIDs;
 | 
			
		||||
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validateId;
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validateIds;
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validatePageLink;
 | 
			
		||||
import static org.thingsboard.server.dao.service.Validator.validateString;
 | 
			
		||||
 | 
			
		||||
@ -277,6 +281,14 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
 | 
			
		||||
        return entityViews;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId) {
 | 
			
		||||
        log.trace("Executing findEntityViewsByTenantIdAndEntityIdAsync, tenantId [{}], entityId [{}]", tenantId, entityId);
 | 
			
		||||
        validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
 | 
			
		||||
        validateId(entityId.getId(), "Incorrect entityId" + entityId);
 | 
			
		||||
        return entityViewDao.findEntityViewsByTenantIdAndEntityIdAsync(tenantId.getId(), entityId.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private DataValidator<EntityView> entityViewValidator =
 | 
			
		||||
            new DataValidator<EntityView>() {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ import org.springframework.data.domain.Pageable;
 | 
			
		||||
import org.springframework.data.jpa.repository.Query;
 | 
			
		||||
import org.springframework.data.repository.CrudRepository;
 | 
			
		||||
import org.springframework.data.repository.query.Param;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.dao.model.sql.EntityViewEntity;
 | 
			
		||||
import org.thingsboard.server.dao.util.SqlDao;
 | 
			
		||||
@ -78,4 +79,6 @@ public interface EntityViewRepository extends CrudRepository<EntityViewEntity, S
 | 
			
		||||
                                                                 List<String> entityViewsIds);
 | 
			
		||||
 | 
			
		||||
    List<EntityViewEntity> findAllByTenantIdAndIdIn(String tenantId, List<String> entityViewsIds);
 | 
			
		||||
 | 
			
		||||
    List<EntityViewEntity> findAllByTenantIdAndEntityId(String tenantId, String entityId);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,7 @@ import org.springframework.stereotype.Component;
 | 
			
		||||
import org.thingsboard.server.common.data.EntitySubtype;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
import org.thingsboard.server.common.data.UUIDConverter;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.page.TextPageLink;
 | 
			
		||||
@ -40,6 +41,7 @@ import java.util.Optional;
 | 
			
		||||
import java.util.UUID;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
 | 
			
		||||
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs;
 | 
			
		||||
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID_STR;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -121,4 +123,10 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao<EntityViewEntity,
 | 
			
		||||
                        new PageRequest(0, pageLink.getLimit())
 | 
			
		||||
                ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ListenableFuture<List<EntityView>> findEntityViewsByTenantIdAndEntityIdAsync(UUID tenantId, UUID entityId) {
 | 
			
		||||
        return service.submit(() -> DaoUtil.convertDataList(
 | 
			
		||||
                entityViewRepository.findAllByTenantIdAndEntityId(UUIDConverter.fromTimeUUID(tenantId), UUIDConverter.fromTimeUUID(entityId))));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@ import org.thingsboard.server.dao.asset.AssetService;
 | 
			
		||||
import org.thingsboard.server.dao.attributes.AttributesService;
 | 
			
		||||
import org.thingsboard.server.dao.customer.CustomerService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceService;
 | 
			
		||||
import org.thingsboard.server.dao.entityview.EntityViewService;
 | 
			
		||||
import org.thingsboard.server.dao.relation.RelationService;
 | 
			
		||||
import org.thingsboard.server.dao.rule.RuleChainService;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantService;
 | 
			
		||||
@ -83,6 +84,8 @@ public interface TbContext {
 | 
			
		||||
 | 
			
		||||
    RelationService getRelationService();
 | 
			
		||||
 | 
			
		||||
    EntityViewService getEntityViewService();
 | 
			
		||||
 | 
			
		||||
    ListeningExecutor getJsExecutor();
 | 
			
		||||
 | 
			
		||||
    ListeningExecutor getMailExecutor();
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,122 @@
 | 
			
		||||
package org.thingsboard.rule.engine.action;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import com.google.common.base.Function;
 | 
			
		||||
import com.google.common.util.concurrent.Futures;
 | 
			
		||||
import com.google.common.util.concurrent.ListenableFuture;
 | 
			
		||||
import com.google.gson.JsonParser;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.thingsboard.rule.engine.api.EmptyNodeConfiguration;
 | 
			
		||||
import org.thingsboard.rule.engine.api.RuleNode;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbContext;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNode;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbNodeException;
 | 
			
		||||
import org.thingsboard.rule.engine.api.TbRelationTypes;
 | 
			
		||||
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
 | 
			
		||||
import org.thingsboard.server.common.data.DataConstants;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityView;
 | 
			
		||||
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
 | 
			
		||||
import org.thingsboard.server.common.data.kv.TsKvEntry;
 | 
			
		||||
import org.thingsboard.server.common.data.plugin.ComponentType;
 | 
			
		||||
import org.thingsboard.server.common.msg.TbMsg;
 | 
			
		||||
import org.thingsboard.server.common.msg.session.SessionMsgType;
 | 
			
		||||
import org.thingsboard.server.common.transport.adaptor.JsonConverter;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.concurrent.ExecutionException;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.thingsboard.rule.engine.api.util.DonAsynchron.withCallback;
 | 
			
		||||
 | 
			
		||||
@Slf4j
 | 
			
		||||
@RuleNode(
 | 
			
		||||
        type = ComponentType.ACTION,
 | 
			
		||||
        name = "copy attributes",
 | 
			
		||||
        configClazz = EmptyNodeConfiguration.class,
 | 
			
		||||
        nodeDescription = "Copy attributes from asset/device to entity view",
 | 
			
		||||
        nodeDetails = "Copy attributes from asset/device to related entity view according to entity view configuration. \n " +
 | 
			
		||||
                "Copy will be done only for attributes that are between start and end dates and according to attribute keys configuration",
 | 
			
		||||
        uiResources = {"static/rulenode/rulenode-core-config.js"},
 | 
			
		||||
        configDirective = "tbNodeEmptyConfig",
 | 
			
		||||
        icon = "content_copy"
 | 
			
		||||
)
 | 
			
		||||
public class TbCopyAttributesToEntityViewNode implements TbNode {
 | 
			
		||||
 | 
			
		||||
    EmptyNodeConfiguration config;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
 | 
			
		||||
        this.config = TbNodeUtils.convert(configuration, EmptyNodeConfiguration.class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException {
 | 
			
		||||
        if (msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ||
 | 
			
		||||
                msg.getType().equals(DataConstants.ATTRIBUTES_DELETED) ||
 | 
			
		||||
                msg.getType().equals(DataConstants.ATTRIBUTES_UPDATED)) {
 | 
			
		||||
            long now = System.currentTimeMillis();
 | 
			
		||||
            String scope;
 | 
			
		||||
            if (msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name())) {
 | 
			
		||||
                scope = DataConstants.CLIENT_SCOPE;
 | 
			
		||||
            } else {
 | 
			
		||||
                scope = msg.getMetaData().getValue("scope");
 | 
			
		||||
            }
 | 
			
		||||
            ListenableFuture<List<EntityView>> entityViewsFuture =
 | 
			
		||||
                    ctx.getEntityViewService().findEntityViewsByTenantIdAndEntityIdAsync(ctx.getTenantId(), msg.getOriginator());
 | 
			
		||||
            withCallback(entityViewsFuture,
 | 
			
		||||
                    entityViews -> {
 | 
			
		||||
                        List<ListenableFuture<List<Void>>> saveFutures = new ArrayList<>();
 | 
			
		||||
                        for (EntityView entityView : entityViews) {
 | 
			
		||||
                            if ((entityView.getEndTimeMs() != 0  && entityView.getEndTimeMs() > now && entityView.getStartTimeMs() < now) ||
 | 
			
		||||
                                    (entityView.getEndTimeMs() == 0 && entityView.getStartTimeMs() < now)) {
 | 
			
		||||
                                Set<AttributeKvEntry> attributes = JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData())).getAttributes();
 | 
			
		||||
                                List<AttributeKvEntry> filteredAttributes =
 | 
			
		||||
                                        attributes.stream()
 | 
			
		||||
                                                .filter(attr -> {
 | 
			
		||||
                                                    switch (scope) {
 | 
			
		||||
                                                        case DataConstants.CLIENT_SCOPE:
 | 
			
		||||
                                                            if (entityView.getKeys().getAttributes().getCs().isEmpty()) {
 | 
			
		||||
                                                                return true;
 | 
			
		||||
                                                            }
 | 
			
		||||
                                                            return entityView.getKeys().getAttributes().getCs().contains(attr.getKey());
 | 
			
		||||
                                                        case DataConstants.SERVER_SCOPE:
 | 
			
		||||
                                                            if (entityView.getKeys().getAttributes().getSs().isEmpty()) {
 | 
			
		||||
                                                                return true;
 | 
			
		||||
                                                            }
 | 
			
		||||
                                                            return entityView.getKeys().getAttributes().getSs().contains(attr.getKey());
 | 
			
		||||
                                                        case  DataConstants.SHARED_SCOPE:
 | 
			
		||||
                                                            if (entityView.getKeys().getAttributes().getSh().isEmpty()) {
 | 
			
		||||
                                                                return true;
 | 
			
		||||
                                                            }
 | 
			
		||||
                                                            return entityView.getKeys().getAttributes().getSh().contains(attr.getKey());
 | 
			
		||||
                                                    }
 | 
			
		||||
                                                    return false;
 | 
			
		||||
                                                })
 | 
			
		||||
                                                .collect(Collectors.toList());
 | 
			
		||||
                                saveFutures.add(ctx.getAttributesService().save(entityView.getId(), scope, new ArrayList<>(filteredAttributes)));
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        Futures.transform(Futures.allAsList(saveFutures), new Function<List<List<Void>>, Object>() {
 | 
			
		||||
                            @Nullable
 | 
			
		||||
                            @Override
 | 
			
		||||
                            public Object apply(@Nullable List<List<Void>> lists) {
 | 
			
		||||
                                ctx.tellNext(msg, TbRelationTypes.SUCCESS);
 | 
			
		||||
                                return null;
 | 
			
		||||
                            }
 | 
			
		||||
                        });
 | 
			
		||||
                    },
 | 
			
		||||
                    t -> ctx.tellFailure(msg, t));
 | 
			
		||||
        } else {
 | 
			
		||||
            ctx.tellNext(msg, TbRelationTypes.FAILURE);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void destroy() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user