Browse Source

Fixed for entity view afte testing

pull/1151/head
Volodymyr Babak 8 years ago
parent
commit
8b1a9351f3
  1. 8
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  2. 85
      application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
  3. 6
      application/src/main/java/org/thingsboard/server/controller/TelemetryController.java
  4. 7
      dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java
  5. 45
      dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
  6. 16
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java
  7. 27
      ui/src/app/api/entity-view.service.js
  8. 4
      ui/src/app/api/entity.service.js

8
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -51,6 +51,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg; import org.thingsboard.server.common.msg.system.ServiceToRuleEngineMsg;
import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.audit.AuditLogService; import org.thingsboard.server.dao.audit.AuditLogService;
import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
@ -70,6 +71,7 @@ import org.thingsboard.server.exception.ThingsboardErrorResponseHandler;
import org.thingsboard.server.service.component.ComponentDiscoveryService; import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
import org.thingsboard.server.service.state.DeviceStateService; import org.thingsboard.server.service.state.DeviceStateService;
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -143,6 +145,12 @@ public abstract class BaseController {
@Autowired @Autowired
protected EntityViewService entityViewService; protected EntityViewService entityViewService;
@Autowired
protected TelemetrySubscriptionService tsSubService;
@Autowired
protected AttributesService attributesService;
@ExceptionHandler(ThingsboardException.class) @ExceptionHandler(ThingsboardException.class)
public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) {
errorResponseHandler.handle(ex, response); errorResponseHandler.handle(ex, response);

85
application/src/main/java/org/thingsboard/server/controller/EntityViewController.java

@ -15,7 +15,10 @@
*/ */
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@ -26,7 +29,9 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.EntityView;
@ -34,15 +39,24 @@ import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.CustomerId; 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.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.common.data.kv.AttributeKvEntry;
import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.msg.cluster.SendToClusterMsg;
import org.thingsboard.server.dao.exception.IncorrectParameterException; import org.thingsboard.server.dao.exception.IncorrectParameterException;
import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.model.SecurityUser;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.thingsboard.server.controller.CustomerController.CUSTOMER_ID; import static org.thingsboard.server.controller.CustomerController.CUSTOMER_ID;
@ -52,6 +66,7 @@ import static org.thingsboard.server.controller.CustomerController.CUSTOMER_ID;
*/ */
@RestController @RestController
@RequestMapping("/api") @RequestMapping("/api")
@Slf4j
public class EntityViewController extends BaseController { public class EntityViewController extends BaseController {
public static final String ENTITY_VIEW_ID = "entityViewId"; public static final String ENTITY_VIEW_ID = "entityViewId";
@ -75,6 +90,20 @@ public class EntityViewController extends BaseController {
try { try {
entityView.setTenantId(getCurrentUser().getTenantId()); entityView.setTenantId(getCurrentUser().getTenantId());
EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView));
List<ListenableFuture<List<Void>>> futures = new ArrayList<>();
if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) {
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs(), getCurrentUser()));
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs(), getCurrentUser()));
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh(), getCurrentUser()));
}
for (ListenableFuture<List<Void>> future : futures) {
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("Failed to copy attributes to entity view", e);
}
}
logEntityAction(savedEntityView.getId(), savedEntityView, null, logEntityAction(savedEntityView.getId(), savedEntityView, null,
entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
return savedEntityView; return savedEntityView;
@ -85,6 +114,62 @@ public class EntityViewController extends BaseController {
} }
} }
private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys, SecurityUser user) throws ThingsboardException {
EntityViewId entityId = entityView.getId();
if (keys != null && !keys.isEmpty()) {
ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
return Futures.transform(getAttrFuture, attributeKvEntries -> {
List<AttributeKvEntry> attributes;
if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) {
attributes =
attributeKvEntries.stream()
.filter(attributeKvEntry -> {
long startTime = entityView.getStartTimeMs();
long endTime = entityView.getEndTimeMs();
long lastUpdateTs = attributeKvEntry.getLastUpdateTs();
return startTime == 0 && endTime == 0 ||
(endTime == 0 && startTime < lastUpdateTs) ||
(startTime == 0 && endTime > lastUpdateTs)
? true : startTime < lastUpdateTs && endTime > lastUpdateTs;
}).collect(Collectors.toList());
tsSubService.saveAndNotify(entityId, scope, attributes, new FutureCallback<Void>() {
@Override
public void onSuccess(@Nullable Void tmp) {
try {
logAttributesUpdated(user, entityId, scope, attributes, null);
} catch (ThingsboardException e) {
log.error("Failed to log attribute updates", e);
}
if (entityId.getEntityType() == EntityType.ENTITY_VIEW) {
DeviceId deviceId = new DeviceId(entityId.getId());
DeviceAttributesEventNotificationMsg notificationMsg = DeviceAttributesEventNotificationMsg.onUpdate(
user.getTenantId(), deviceId, scope, attributes);
actorService.onMsg(new SendToClusterMsg(deviceId, notificationMsg));
}
}
@Override
public void onFailure(Throwable t) {
try {
logAttributesUpdated(user, entityId, scope, attributes, t);
} catch (ThingsboardException e) {
log.error("Failed to log attribute updates", e);
}
}
});
}
return null;
});
} else {
return Futures.immediateFuture(null);
}
}
private void logAttributesUpdated(SecurityUser user, EntityId entityId, String scope, List<AttributeKvEntry> attributes, Throwable e) throws ThingsboardException {
logEntityAction(user, (UUIDBased & EntityId) entityId, null, null, ActionType.ATTRIBUTES_UPDATED, toException(e),
scope, attributes);
}
@PreAuthorize("hasAuthority('TENANT_ADMIN')") @PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE) @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)

6
application/src/main/java/org/thingsboard/server/controller/TelemetryController.java

@ -93,15 +93,9 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
public class TelemetryController extends BaseController { public class TelemetryController extends BaseController {
@Autowired
private AttributesService attributesService;
@Autowired @Autowired
private TimeseriesService tsService; private TimeseriesService tsService;
@Autowired
private TelemetrySubscriptionService tsSubService;
@Autowired @Autowired
private AccessValidator accessValidator; private AccessValidator accessValidator;

7
dao/src/main/java/org/thingsboard/server/dao/entity/BaseEntityService.java

@ -29,6 +29,7 @@ import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entityview.EntityViewService;
import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.user.UserService; import org.thingsboard.server.dao.user.UserService;
@ -46,6 +47,9 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
@Autowired @Autowired
private DeviceService deviceService; private DeviceService deviceService;
@Autowired
private EntityViewService entityViewService;
@Autowired @Autowired
private TenantService tenantService; private TenantService tenantService;
@ -81,6 +85,9 @@ public class BaseEntityService extends AbstractEntityService implements EntitySe
case DEVICE: case DEVICE:
hasName = deviceService.findDeviceByIdAsync(new DeviceId(entityId.getId())); hasName = deviceService.findDeviceByIdAsync(new DeviceId(entityId.getId()));
break; break;
case ENTITY_VIEW:
hasName = entityViewService.findEntityViewByIdAsync(new EntityViewId(entityId.getId()));
break;
case TENANT: case TENANT:
hasName = tenantService.findTenantByIdAsync(new TenantId(entityId.getId())); hasName = tenantService.findTenantByIdAsync(new TenantId(entityId.getId()));
break; break;

45
dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java

@ -105,21 +105,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
log.trace("Executing save entity view [{}]", entityView); log.trace("Executing save entity view [{}]", entityView);
entityViewValidator.validate(entityView); entityViewValidator.validate(entityView);
EntityView savedEntityView = entityViewDao.save(entityView); EntityView savedEntityView = entityViewDao.save(entityView);
List<ListenableFuture<List<Void>>> futures = new ArrayList<>();
if (savedEntityView.getKeys() != null && savedEntityView.getKeys().getAttributes() != null) {
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.CLIENT_SCOPE, savedEntityView.getKeys().getAttributes().getCs()));
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SERVER_SCOPE, savedEntityView.getKeys().getAttributes().getSs()));
futures.add(copyAttributesFromEntityToEntityView(savedEntityView, DataConstants.SHARED_SCOPE, savedEntityView.getKeys().getAttributes().getSh()));
}
for (ListenableFuture<List<Void>> future : futures) {
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
log.error("Failed to copy attributes to entity view", e);
throw new RuntimeException("Failed to copy attributes to entity view", e);
}
}
return savedEntityView; return savedEntityView;
} }
@ -294,36 +279,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
}); });
} }
private ListenableFuture<List<Void>> copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection<String> keys) {
if (keys != null && !keys.isEmpty()) {
ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
return Futures.transform(getAttrFuture, attributeKvEntries -> {
List<AttributeKvEntry> filteredAttributes = new ArrayList<>();
if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) {
filteredAttributes =
attributeKvEntries.stream()
.filter(attributeKvEntry -> {
long startTime = entityView.getStartTimeMs();
long endTime = entityView.getEndTimeMs();
long lastUpdateTs = attributeKvEntry.getLastUpdateTs();
return startTime == 0 && endTime == 0 ||
(endTime == 0 && startTime < lastUpdateTs) ||
(startTime == 0 && endTime > lastUpdateTs)
? true : startTime < lastUpdateTs && endTime > lastUpdateTs;
}).collect(Collectors.toList());
}
try {
return attributesService.save(entityView.getId(), scope, filteredAttributes).get();
} catch (InterruptedException | ExecutionException e) {
log.error("Failed to copy attributes to entity view", e);
throw new RuntimeException("Failed to copy attributes to entity view", e);
}
});
} else {
return Futures.immediateFuture(null);
}
}
private DataValidator<EntityView> entityViewValidator = private DataValidator<EntityView> entityViewValidator =
new DataValidator<EntityView>() { new DataValidator<EntityView>() {

16
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java

@ -116,8 +116,10 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
} }
List<String> filteredAttributes = List<String> filteredAttributes =
attributes.stream().filter(attr -> attributeContainsInEntityView(scope, attr, entityView)).collect(Collectors.toList()); attributes.stream().filter(attr -> attributeContainsInEntityView(scope, attr, entityView)).collect(Collectors.toList());
ctx.getAttributesService().removeAll(entityView.getId(), scope, filteredAttributes); if (filteredAttributes != null && !filteredAttributes.isEmpty()) {
transformAndTellNext(ctx, msg, entityView); ctx.getAttributesService().removeAll(entityView.getId(), scope, filteredAttributes);
transformAndTellNext(ctx, msg, entityView);
}
} }
} }
} }
@ -139,19 +141,10 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
private boolean attributeContainsInEntityView(String scope, String attrKey, EntityView entityView) { private boolean attributeContainsInEntityView(String scope, String attrKey, EntityView entityView) {
switch (scope) { switch (scope) {
case DataConstants.CLIENT_SCOPE: case DataConstants.CLIENT_SCOPE:
if (entityView.getKeys().getAttributes().getCs().isEmpty()) {
return true;
}
return entityView.getKeys().getAttributes().getCs().contains(attrKey); return entityView.getKeys().getAttributes().getCs().contains(attrKey);
case DataConstants.SERVER_SCOPE: case DataConstants.SERVER_SCOPE:
if (entityView.getKeys().getAttributes().getSs().isEmpty()) {
return true;
}
return entityView.getKeys().getAttributes().getSs().contains(attrKey); return entityView.getKeys().getAttributes().getSs().contains(attrKey);
case DataConstants.SHARED_SCOPE: case DataConstants.SHARED_SCOPE:
if (entityView.getKeys().getAttributes().getSh().isEmpty()) {
return true;
}
return entityView.getKeys().getAttributes().getSh().contains(attrKey); return entityView.getKeys().getAttributes().getSh().contains(attrKey);
} }
return false; return false;
@ -159,6 +152,5 @@ public class TbCopyAttributesToEntityViewNode implements TbNode {
@Override @Override
public void destroy() { public void destroy() {
} }
} }

27
ui/src/app/api/entity-view.service.js

@ -27,7 +27,6 @@ function EntityViewService($http, $q, $window, userService, attributeService, cu
deleteEntityView: deleteEntityView, deleteEntityView: deleteEntityView,
getCustomerEntityViews: getCustomerEntityViews, getCustomerEntityViews: getCustomerEntityViews,
getEntityView: getEntityView, getEntityView: getEntityView,
getEntityViews: getEntityViews,
getTenantEntityViews: getTenantEntityViews, getTenantEntityViews: getTenantEntityViews,
saveEntityView: saveEntityView, saveEntityView: saveEntityView,
unassignEntityViewFromCustomer: unassignEntityViewFromCustomer, unassignEntityViewFromCustomer: unassignEntityViewFromCustomer,
@ -126,32 +125,6 @@ function EntityViewService($http, $q, $window, userService, attributeService, cu
return deferred.promise; return deferred.promise;
} }
function getEntityViews(entityViewIds, config) {
var deferred = $q.defer();
var ids = '';
for (var i=0;i<entityViewIds.length;i++) {
if (i>0) {
ids += ',';
}
ids += entityViewIds[i];
}
var url = '/api/entityViews?entityViewIds=' + ids;
$http.get(url, config).then(function success(response) {
var entityViews = response.data;
entityViews.sort(function (entityView1, entityView2) {
var id1 = entityView1.id.id;
var id2 = entityView2.id.id;
var index1 = entityViewIds.indexOf(id1);
var index2 = entityViewIds.indexOf(id2);
return index1 - index2;
});
deferred.resolve(entityViews);
}, function fail(response) {
deferred.reject(response.data);
});
return deferred.promise;
}
function saveEntityView(entityView) { function saveEntityView(entityView) {
var deferred = $q.defer(); var deferred = $q.defer();
var url = '/api/entityView'; var url = '/api/entityView';

4
ui/src/app/api/entity.service.js

@ -135,6 +135,10 @@ function EntityService($http, $q, $filter, $translate, $log, userService, device
case types.entityType.asset: case types.entityType.asset:
promise = assetService.getAssets(entityIds, config); promise = assetService.getAssets(entityIds, config);
break; break;
case types.entityType.entityView:
promise = getEntitiesByIdsPromise(
(id) => entityViewService.getEntityView(id, config), entityIds);
break;
case types.entityType.tenant: case types.entityType.tenant:
promise = getEntitiesByIdsPromise( promise = getEntitiesByIdsPromise(
(id) => tenantService.getTenant(id, config), entityIds); (id) => tenantService.getTenant(id, config), entityIds);

Loading…
Cancel
Save