Browse Source

Merge remote-tracking branch 'origin/feature/edge' into feature/edge

pull/2436/head
deaflynx 6 years ago
parent
commit
8db3df0388
  1. 1
      .gitignore
  2. 32
      application/src/main/data/upgrade/2.6.0/schema_update_ttl.sql
  3. 3
      application/src/main/java/org/thingsboard/server/controller/AlarmController.java
  4. 13
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  5. 2
      application/src/main/java/org/thingsboard/server/controller/AuthController.java
  6. 18
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  7. 12
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  8. 12
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  9. 6
      application/src/main/java/org/thingsboard/server/controller/EdgeController.java
  10. 12
      application/src/main/java/org/thingsboard/server/controller/EntityViewController.java
  11. 18
      application/src/main/java/org/thingsboard/server/controller/RuleChainController.java
  12. 5
      application/src/main/java/org/thingsboard/server/controller/UserController.java
  13. 12
      application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java
  14. 11
      application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java
  15. 125
      application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java
  16. 30
      application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java
  17. 788
      application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java
  18. 41
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java
  19. 72
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java
  20. 8
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java
  21. 4
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java
  22. 61
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java
  23. 54
      application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java
  24. 187
      application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java
  25. 11
      application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java
  26. 56
      application/src/main/java/org/thingsboard/server/service/ttl/edge/EdgeEventsCleanUpService.java
  27. 4
      application/src/main/resources/thingsboard.yml
  28. 13
      common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java
  29. 6
      common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java
  30. 4
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java
  31. 38
      common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java
  32. 7
      common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java
  33. 91
      common/edge-api/src/main/proto/edge.proto
  34. 8
      common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java
  35. 17
      dao/src/main/resources/sql/schema-entities.sql
  36. 1
      pom.xml
  37. 113
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java

1
.gitignore

@ -33,3 +33,4 @@ pom.xml.versionsBackup
**/.env
.instance_id
rebuild-docker.sh
.run/

32
application/src/main/data/upgrade/2.6.0/schema_update_ttl.sql

@ -0,0 +1,32 @@
--
-- Copyright © 2016-2020 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.
--
CREATE OR REPLACE PROCEDURE cleanup_edge_events_by_ttl(IN ttl bigint, INOUT deleted bigint)
LANGUAGE plpgsql AS
$$
DECLARE
ttl_ts bigint;
ttl_deleted_count bigint DEFAULT 0;
BEGIN
IF ttl > 0 THEN
ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - ttl::bigint * 1000)::bigint;
EXECUTE format(
'WITH deleted AS (DELETE FROM edge_event WHERE ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', ttl_ts) into ttl_deleted_count;
END IF;
RAISE NOTICE 'Edge events removed by ttl: %', ttl_deleted_count;
deleted := ttl_deleted_count;
END
$$;

3
application/src/main/java/org/thingsboard/server/controller/AlarmController.java

@ -92,7 +92,8 @@ public class AlarmController extends BaseController {
getCurrentUser().getCustomerId(),
alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
sendNotificationMsgToEdgeService(getTenantId(), savedAlarm.getId(), alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
sendNotificationMsgToEdgeService(getTenantId(), savedAlarm.getId(),
alarm.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return savedAlarm;
} catch (Exception e) {

13
application/src/main/java/org/thingsboard/server/controller/AssetController.java

@ -88,13 +88,13 @@ public class AssetController extends BaseController {
Asset savedAsset = checkNotNull(assetService.saveAsset(asset));
sendNotificationMsgToEdgeService(savedAsset.getTenantId(), null,
savedAsset.getId(), EdgeEventType.ASSET, asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
logEntityAction(savedAsset.getId(), savedAsset,
savedAsset.getCustomerId(),
asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
sendNotificationMsgToEdgeService(getTenantId(), savedAsset.getId(),
asset.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return savedAsset;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET), asset,
@ -117,7 +117,7 @@ public class AssetController extends BaseController {
asset.getCustomerId(),
ActionType.DELETED, null, strAssetId);
sendNotificationMsgToEdgeService(getTenantId(), null, assetId, EdgeEventType.ASSET, ActionType.DELETED);
sendNotificationMsgToEdgeService(getTenantId(), assetId, ActionType.DELETED);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ASSET),
null,
@ -360,7 +360,7 @@ public class AssetController extends BaseController {
savedAsset.getCustomerId(),
ActionType.ASSIGNED_TO_EDGE, null, strAssetId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(), EdgeEventType.ASSET, ActionType.ASSIGNED_TO_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(), ActionType.ASSIGNED_TO_EDGE);
return savedAsset;
} catch (Exception e) {
@ -393,8 +393,7 @@ public class AssetController extends BaseController {
asset.getCustomerId(),
ActionType.UNASSIGNED_FROM_EDGE, null, strAssetId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(),
EdgeEventType.ASSET, ActionType.UNASSIGNED_FROM_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedAsset.getId(), ActionType.UNASSIGNED_FROM_EDGE);
return savedAsset;
} catch (Exception e) {

2
application/src/main/java/org/thingsboard/server/controller/AuthController.java

@ -126,7 +126,7 @@ public class AuthController extends BaseController {
userCredentials.setPassword(passwordEncoder.encode(newPassword));
userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials);
sendNotificationMsgToEdgeService(getTenantId(), null, userCredentials.getUserId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED);
sendNotificationMsgToEdgeService(getTenantId(), userCredentials.getUserId(), ActionType.CREDENTIALS_UPDATED);
} catch (Exception e) {
throw handleException(e);

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

@ -718,6 +718,14 @@ public abstract class BaseController {
return result;
}
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, CustomerId customerId, ActionType edgeEventAction) {
try {
sendNotificationMsgToEdgeService(tenantId, edgeId, null, json.writeValueAsString(customerId), EdgeEventType.EDGE, edgeEventAction);
} catch (Exception e) {
log.warn("Failed to push assign/unassign to/from customer to core: {}", customerId, e);
}
}
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityRelation relation, ActionType edgeEventAction) {
try {
if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) &&
@ -730,16 +738,16 @@ public abstract class BaseController {
}
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EntityId entityId, ActionType edgeEventAction) {
sendNotificationMsgToEdgeService(tenantId, null, entityId, edgeEventAction);
}
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, ActionType edgeEventAction) {
EdgeEventType edgeEventType = EdgeUtils.getEdgeEventTypeByEntityType(entityId.getEntityType());
if (edgeEventType != null) {
sendNotificationMsgToEdgeService(tenantId, null, entityId, null, edgeEventType, edgeEventAction);
sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, edgeEventType, edgeEventAction);
}
}
protected void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, EdgeEventType edgeEventType, ActionType edgeEventAction) {
sendNotificationMsgToEdgeService(tenantId, edgeId, entityId, null, edgeEventType, edgeEventAction);
}
private void sendNotificationMsgToEdgeService(TenantId tenantId, EdgeId edgeId, EntityId entityId, String entityBody, EdgeEventType edgeEventType, ActionType edgeEventAction) {
TransportProtos.EdgeNotificationMsgProto.Builder builder = TransportProtos.EdgeNotificationMsgProto.newBuilder();
builder.setTenantIdMSB(tenantId.getId().getMostSignificantBits());

12
application/src/main/java/org/thingsboard/server/controller/DashboardController.java

@ -117,8 +117,8 @@ public class DashboardController extends BaseController {
null,
dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), null, savedDashboard.getId(),
EdgeEventType.DASHBOARD, savedDashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
sendNotificationMsgToEdgeService(savedDashboard.getTenantId(), savedDashboard.getId(),
dashboard.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return savedDashboard;
} catch (Exception e) {
@ -143,7 +143,7 @@ public class DashboardController extends BaseController {
null,
ActionType.DELETED, null, strDashboardId);
sendNotificationMsgToEdgeService(getTenantId(), null, dashboardId, EdgeEventType.DASHBOARD, ActionType.DELETED);
sendNotificationMsgToEdgeService(getTenantId(), dashboardId, ActionType.DELETED);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.DASHBOARD),
@ -500,8 +500,7 @@ public class DashboardController extends BaseController {
null,
ActionType.ASSIGNED_TO_EDGE, null, strDashboardId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(),
EdgeEventType.DASHBOARD, ActionType.ASSIGNED_TO_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(), ActionType.ASSIGNED_TO_EDGE);
return savedDashboard;
} catch (Exception e) {
@ -533,8 +532,7 @@ public class DashboardController extends BaseController {
null,
ActionType.UNASSIGNED_FROM_EDGE, null, strDashboardId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(),
EdgeEventType.DASHBOARD, ActionType.UNASSIGNED_FROM_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDashboard.getId(), ActionType.UNASSIGNED_FROM_EDGE);
return savedDashboard;
} catch (Exception e) {

12
application/src/main/java/org/thingsboard/server/controller/DeviceController.java

@ -108,8 +108,8 @@ public class DeviceController extends BaseController {
tbClusterService.pushMsgToCore(new DeviceNameOrTypeUpdateMsg(savedDevice.getTenantId(),
savedDevice.getId(), savedDevice.getName(), savedDevice.getType()), null);
sendNotificationMsgToEdgeService(savedDevice.getTenantId(), null, savedDevice.getId(),
EdgeEventType.DEVICE, device.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
sendNotificationMsgToEdgeService(savedDevice.getTenantId(), savedDevice.getId(),
device.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
logEntityAction(savedDevice.getId(), savedDevice,
savedDevice.getCustomerId(),
@ -142,7 +142,7 @@ public class DeviceController extends BaseController {
device.getCustomerId(),
ActionType.DELETED, null, strDeviceId);
sendNotificationMsgToEdgeService(getTenantId(), null, deviceId, EdgeEventType.DEVICE, ActionType.DELETED);
sendNotificationMsgToEdgeService(getTenantId(), deviceId, ActionType.DELETED);
deviceStateService.onDeviceDeleted(device);
} catch (Exception e) {
@ -267,7 +267,7 @@ public class DeviceController extends BaseController {
tbClusterService.pushMsgToCore(new DeviceCredentialsUpdateNotificationMsg(getCurrentUser().getTenantId(), deviceCredentials.getDeviceId()), null);
sendNotificationMsgToEdgeService(getTenantId(), null, device.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED);
sendNotificationMsgToEdgeService(getTenantId(), device.getId(), ActionType.CREDENTIALS_UPDATED);
logEntityAction(device.getId(), device,
device.getCustomerId(),
@ -518,7 +518,7 @@ public class DeviceController extends BaseController {
savedDevice.getCustomerId(),
ActionType.ASSIGNED_TO_EDGE, null, strDeviceId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), EdgeEventType.DEVICE, ActionType.ASSIGNED_TO_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), ActionType.ASSIGNED_TO_EDGE);
return savedDevice;
} catch (Exception e) {
@ -549,7 +549,7 @@ public class DeviceController extends BaseController {
device.getCustomerId(),
ActionType.UNASSIGNED_FROM_EDGE, null, strDeviceId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), EdgeEventType.DEVICE, ActionType.UNASSIGNED_FROM_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedDevice.getId(), ActionType.UNASSIGNED_FROM_EDGE);
return savedDevice;
} catch (Exception e) {

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

@ -178,6 +178,9 @@ public class EdgeController extends BaseController {
savedEdge.getCustomerId(),
ActionType.ASSIGNED_TO_CUSTOMER, null, strEdgeId, strCustomerId, customer.getName());
sendNotificationMsgToEdgeService(savedEdge.getTenantId(), savedEdge.getId(),
customerId, ActionType.ASSIGNED_TO_CUSTOMER);
return savedEdge;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.EDGE), null,
@ -206,6 +209,9 @@ public class EdgeController extends BaseController {
edge.getCustomerId(),
ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEdgeId, customer.getId().toString(), customer.getName());
sendNotificationMsgToEdgeService(savedEdge.getTenantId(), savedEdge.getId(),
edge.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER);
return savedEdge;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.EDGE), null,

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

@ -118,8 +118,8 @@ public class EntityViewController extends BaseController {
logEntityAction(savedEntityView.getId(), savedEntityView, null,
entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
sendNotificationMsgToEdgeService(getTenantId(), null, savedEntityView.getId(),
EdgeEventType.ENTITY_VIEW, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
sendNotificationMsgToEdgeService(getTenantId(), savedEntityView.getId(),
entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return savedEntityView;
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null,
@ -190,7 +190,7 @@ public class EntityViewController extends BaseController {
logEntityAction(entityViewId, entityView, entityView.getCustomerId(),
ActionType.DELETED, null, strEntityViewId);
sendNotificationMsgToEdgeService(getTenantId(), null, entityViewId, EdgeEventType.ENTITY_VIEW, ActionType.DELETED);
sendNotificationMsgToEdgeService(getTenantId(), entityViewId, ActionType.DELETED);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.ENTITY_VIEW),
null,
@ -396,8 +396,7 @@ public class EntityViewController extends BaseController {
savedEntityView.getCustomerId(),
ActionType.ASSIGNED_TO_EDGE, null, strEntityViewId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(),
EdgeEventType.ENTITY_VIEW, ActionType.ASSIGNED_TO_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(), ActionType.ASSIGNED_TO_EDGE);
return savedEntityView;
} catch (Exception e) {
@ -427,8 +426,7 @@ public class EntityViewController extends BaseController {
entityView.getCustomerId(),
ActionType.UNASSIGNED_FROM_EDGE, null, strEntityViewId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(),
EdgeEventType.ENTITY_VIEW, ActionType.UNASSIGNED_FROM_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedEntityView.getId(), ActionType.UNASSIGNED_FROM_EDGE);
return savedEntityView;
} catch (Exception e) {

18
application/src/main/java/org/thingsboard/server/controller/RuleChainController.java

@ -145,9 +145,8 @@ public class RuleChainController extends BaseController {
created ? ActionType.ADDED : ActionType.UPDATED, null);
if (RuleChainType.EDGE.equals(savedRuleChain.getType())) {
sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(), null,
savedRuleChain.getId(), EdgeEventType.RULE_CHAIN,
savedRuleChain.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
sendNotificationMsgToEdgeService(savedRuleChain.getTenantId(), savedRuleChain.getId(),
created ? ActionType.ADDED : ActionType.UPDATED);
}
return savedRuleChain;
@ -226,9 +225,7 @@ public class RuleChainController extends BaseController {
if (RuleChainType.EDGE.equals(ruleChain.getType())) {
sendNotificationMsgToEdgeService(ruleChain.getTenantId(),
null,
ruleChain.getId(), EdgeEventType.RULE_CHAIN,
ActionType.UPDATED);
ruleChain.getId(), ActionType.UPDATED);
}
return savedRuleChainMetaData;
@ -293,8 +290,7 @@ public class RuleChainController extends BaseController {
ActionType.DELETED, null, strRuleChainId);
if (RuleChainType.EDGE.equals(ruleChain.getType())) {
sendNotificationMsgToEdgeService(ruleChain.getTenantId(), null,
ruleChain.getId(), EdgeEventType.RULE_CHAIN, ActionType.DELETED);
sendNotificationMsgToEdgeService(ruleChain.getTenantId(), ruleChain.getId(), ActionType.DELETED);
}
} catch (Exception e) {
@ -426,8 +422,7 @@ public class RuleChainController extends BaseController {
null,
ActionType.ASSIGNED_TO_EDGE, null, strRuleChainId, strEdgeId, edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(),
EdgeEventType.RULE_CHAIN, ActionType.ASSIGNED_TO_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(), ActionType.ASSIGNED_TO_EDGE);
return savedRuleChain;
} catch (Exception e) {
@ -459,8 +454,7 @@ public class RuleChainController extends BaseController {
null,
ActionType.UNASSIGNED_FROM_EDGE, null, strRuleChainId, edge.getId().toString(), edge.getName());
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(),
EdgeEventType.RULE_CHAIN, ActionType.UNASSIGNED_FROM_EDGE);
sendNotificationMsgToEdgeService(getTenantId(), edgeId, savedRuleChain.getId(), ActionType.UNASSIGNED_FROM_EDGE);
return savedRuleChain;
} catch (Exception e) {

5
application/src/main/java/org/thingsboard/server/controller/UserController.java

@ -162,7 +162,8 @@ public class UserController extends BaseController {
savedUser.getCustomerId(),
user.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null);
sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, user.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
sendNotificationMsgToEdgeService(getTenantId(), savedUser.getId(),
user.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return savedUser;
} catch (Exception e) {
@ -239,7 +240,7 @@ public class UserController extends BaseController {
user.getCustomerId(),
ActionType.DELETED, null, strUserId);
sendNotificationMsgToEdgeService(getTenantId(), null, user.getId(), EdgeEventType.USER, ActionType.DELETED);
sendNotificationMsgToEdgeService(getTenantId(), user.getId(), ActionType.DELETED);
} catch (Exception e) {
logEntityAction(emptyId(EntityType.USER),

12
application/src/main/java/org/thingsboard/server/controller/WidgetTypeController.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
@ -25,6 +26,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId;
@ -37,6 +39,7 @@ import org.thingsboard.server.service.security.permission.Resource;
import java.util.List;
@Slf4j
@RestController
@TbCoreComponent
@RequestMapping("/api")
@ -67,8 +70,12 @@ public class WidgetTypeController extends BaseController {
}
checkEntity(widgetType.getId(), widgetType, Resource.WIDGET_TYPE);
WidgetType savedWidgetType = widgetTypeService.saveWidgetType(widgetType);
return checkNotNull(widgetTypeService.saveWidgetType(widgetType));
sendNotificationMsgToEdgeService(getTenantId(), savedWidgetType.getId(),
widgetType.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return checkNotNull(savedWidgetType);
} catch (Exception e) {
throw handleException(e);
}
@ -83,6 +90,9 @@ public class WidgetTypeController extends BaseController {
WidgetTypeId widgetTypeId = new WidgetTypeId(toUUID(strWidgetTypeId));
checkWidgetTypeId(widgetTypeId, Operation.DELETE);
widgetTypeService.deleteWidgetType(getCurrentUser().getTenantId(), widgetTypeId);
sendNotificationMsgToEdgeService(getTenantId(), widgetTypeId, ActionType.DELETED);
} catch (Exception e) {
throw handleException(e);
}

11
application/src/main/java/org/thingsboard/server/controller/WidgetsBundleController.java

@ -25,6 +25,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetsBundleId;
@ -68,7 +69,12 @@ public class WidgetsBundleController extends BaseController {
}
checkEntity(widgetsBundle.getId(), widgetsBundle, Resource.WIDGETS_BUNDLE);
return checkNotNull(widgetsBundleService.saveWidgetsBundle(widgetsBundle));
WidgetsBundle savedWidgetsBundle = widgetsBundleService.saveWidgetsBundle(widgetsBundle);
sendNotificationMsgToEdgeService(getTenantId(), savedWidgetsBundle.getId(),
widgetsBundle.getId() == null ? ActionType.ADDED : ActionType.UPDATED);
return checkNotNull(savedWidgetsBundle);
} catch (Exception e) {
throw handleException(e);
}
@ -83,6 +89,9 @@ public class WidgetsBundleController extends BaseController {
WidgetsBundleId widgetsBundleId = new WidgetsBundleId(toUUID(strWidgetsBundleId));
checkWidgetsBundleId(widgetsBundleId, Operation.DELETE);
widgetsBundleService.deleteWidgetsBundle(getTenantId(), widgetsBundleId);
sendNotificationMsgToEdgeService(getTenantId(), widgetsBundleId, ActionType.DELETED);
} catch (Exception e) {
throw handleException(e);
}

125
application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java

@ -18,9 +18,11 @@ package org.thingsboard.server.service.edge;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityType;
@ -46,12 +48,15 @@ import org.thingsboard.server.common.data.page.TimePageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
import org.thingsboard.server.common.msg.queue.TbCallback;
import org.thingsboard.server.dao.alarm.AlarmService;
import org.thingsboard.server.dao.edge.EdgeEventService;
import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.gen.transport.TransportProtos;
import org.thingsboard.server.queue.util.TbCoreComponent;
@ -86,6 +91,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
@Autowired
private UserService userService;
@Autowired
private RuleChainService ruleChainService;
@Autowired
private RelationService relationService;
@ -149,14 +157,17 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
TenantId tenantId = new TenantId(new UUID(edgeNotificationMsg.getTenantIdMSB(), edgeNotificationMsg.getTenantIdLSB()));
EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType());
switch (edgeEventType) {
// TODO: voba - handle edge updates
// case EDGE:
case EDGE:
processEdge(tenantId, edgeNotificationMsg);
break;
case USER:
case ASSET:
case DEVICE:
case ENTITY_VIEW:
case DASHBOARD:
case RULE_CHAIN:
case WIDGETS_BUNDLE:
case WIDGET_TYPE:
processEntity(tenantId, edgeNotificationMsg);
break;
case ALARM:
@ -176,29 +187,76 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
}
}
private void processEdge(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
// TODO: voba - handle edge updates
try {
ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction());
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
switch (edgeEventActionType) {
case ASSIGNED_TO_CUSTOMER:
case UNASSIGNED_FROM_CUSTOMER:
CustomerId customerId = mapper.readValue(edgeNotificationMsg.getEntityBody(), CustomerId.class);
ListenableFuture<Edge> edgeFuture = edgeService.findEdgeByIdAsync(tenantId, edgeId);
Futures.addCallback(edgeFuture, new FutureCallback<Edge>() {
@Override
public void onSuccess(@Nullable Edge edge) {
if (edge != null && customerId != null && !EntityId.NULL_UUID.equals(customerId.getId())) {
ActionType actionType = ActionType.ASSIGNED_TO_CUSTOMER.equals(edgeEventActionType) ? ActionType.ADDED : ActionType.DELETED;
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, actionType, customerId, null);
TextPageData<User> pageData = userService.findCustomerUsers(tenantId, customerId, new TextPageLink(Integer.MAX_VALUE));
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] user(s) are going to be {} to edge.", edge.getId(), pageData.getData().size(), actionType.name());
for (User user : pageData.getData()) {
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, actionType, user.getId(), null);
}
}
}
}
@Override
public void onFailure(Throwable t) {
log.error("Can't find edge by id [{}]", edgeNotificationMsg, t);
}
}, dbCallbackExecutorService);
break;
}
} catch (Exception e) {
log.error("Exception during processing edge event", e);
}
}
private void processEntity(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
ActionType edgeEventActionType = ActionType.valueOf(edgeNotificationMsg.getEdgeEventAction());
EdgeEventType edgeEventType = EdgeEventType.valueOf(edgeNotificationMsg.getEdgeEventType());
EntityId entityId = EntityIdFactory.getByEdgeEventTypeAndUuid(edgeEventType, new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
switch (edgeEventActionType) {
// TODO: voba - ADDED is not required for CE version ?
// case ADDED:
case ADDED:
case UPDATED:
case CREDENTIALS_UPDATED:
ListenableFuture<List<EdgeId>> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId);
Futures.transform(edgeIdsFuture, edgeIds -> {
if (edgeIds != null && !edgeIds.isEmpty()) {
for (EdgeId edgeId : edgeIds) {
try {
saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null);
} catch (Exception e) {
log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]",
tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e);
}
if (edgeEventType.equals(EdgeEventType.WIDGETS_BUNDLE) || edgeEventType.equals(EdgeEventType.WIDGET_TYPE)) {
TextPageData<Edge> edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE));
if (edgesByTenantId != null && edgesByTenantId.getData() != null && !edgesByTenantId.getData().isEmpty()) {
for (Edge edge : edgesByTenantId.getData()) {
saveEdgeEvent(tenantId, edge.getId(), edgeEventType, edgeEventActionType, entityId, null);
}
}
return null;
}, dbCallbackExecutorService);
} else {
ListenableFuture<List<EdgeId>> edgeIdsFuture = findRelatedEdgeIdsByEntityId(tenantId, entityId);
Futures.transform(edgeIdsFuture, edgeIds -> {
if (edgeIds != null && !edgeIds.isEmpty()) {
for (EdgeId edgeId : edgeIds) {
try {
saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null);
} catch (Exception e) {
log.error("[{}] Failed to push event to edge, edgeId [{}], edgeEventType [{}], edgeEventActionType [{}], entityId [{}]",
tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, e);
}
}
}
return null;
}, dbCallbackExecutorService);
}
break;
case DELETED:
TextPageData<Edge> edgesByTenantId = edgeService.findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE));
@ -212,6 +270,9 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
case UNASSIGNED_FROM_EDGE:
EdgeId edgeId = new EdgeId(new UUID(edgeNotificationMsg.getEdgeIdMSB(), edgeNotificationMsg.getEdgeIdLSB()));
saveEdgeEvent(tenantId, edgeId, edgeEventType, edgeEventActionType, entityId, null);
if (edgeEventType.equals(EdgeEventType.RULE_CHAIN)) {
updateDependentRuleChains(tenantId, new RuleChainId(entityId.getId()), edgeId);
}
break;
case RELATIONS_DELETED:
// TODO: voba - add support for relations deleted
@ -219,6 +280,40 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
}
}
private void updateDependentRuleChains(TenantId tenantId, RuleChainId processingRuleChainId, EdgeId edgeId) {
ListenableFuture<TimePageData<RuleChain>> future = ruleChainService.findRuleChainsByTenantIdAndEdgeId(tenantId, edgeId, new TimePageLink(Integer.MAX_VALUE));
Futures.addCallback(future, new FutureCallback<TimePageData<RuleChain>>() {
@Override
public void onSuccess(@Nullable TimePageData<RuleChain> pageData) {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
for (RuleChain ruleChain : pageData.getData()) {
if (!ruleChain.getId().equals(processingRuleChainId)) {
List<RuleChainConnectionInfo> connectionInfos =
ruleChainService.loadRuleChainMetaData(ruleChain.getTenantId(), ruleChain.getId()).getRuleChainConnections();
if (connectionInfos != null && !connectionInfos.isEmpty()) {
for (RuleChainConnectionInfo connectionInfo : connectionInfos) {
if (connectionInfo.getTargetRuleChainId().equals(processingRuleChainId)) {
saveEdgeEvent(tenantId,
edgeId,
EdgeEventType.RULE_CHAIN_METADATA,
ActionType.UPDATED,
ruleChain.getId(),
null);
}
}
}
}
}
}
}
@Override
public void onFailure(Throwable t) {
log.error("Exception during updating dependent rule chains on sync!", t);
}
}, dbCallbackExecutorService);
}
private void processAlarm(TenantId tenantId, TransportProtos.EdgeNotificationMsgProto edgeNotificationMsg) {
AlarmId alarmId = new AlarmId(new UUID(edgeNotificationMsg.getEntityIdMSB(), edgeNotificationMsg.getEntityIdLSB()));
ListenableFuture<Alarm> alarmFuture = alarmService.findAlarmByIdAsync(tenantId, alarmId);

30
application/src/main/java/org/thingsboard/server/service/edge/EdgeContextComponent.java

@ -33,12 +33,16 @@ 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.user.UserService;
import org.thingsboard.server.dao.widget.WidgetTypeService;
import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.queue.discovery.PartitionService;
import org.thingsboard.server.queue.provider.TbQueueProducerProvider;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.EdgeEventStorageSettings;
import org.thingsboard.server.service.edge.rpc.constructor.AdminSettingsUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.AlarmUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.AssetUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.CustomerUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.DashboardUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.DeviceUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.EntityDataMsgConstructor;
@ -46,6 +50,8 @@ import org.thingsboard.server.service.edge.rpc.constructor.EntityViewUpdateMsgCo
import org.thingsboard.server.service.edge.rpc.constructor.RelationUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.RuleChainUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.UserUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.WidgetTypeUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.constructor.WidgetsBundleUpdateMsgConstructor;
import org.thingsboard.server.service.edge.rpc.init.SyncEdgeService;
import org.thingsboard.server.service.executors.DbCallbackExecutorService;
import org.thingsboard.server.service.queue.TbClusterService;
@ -119,6 +125,14 @@ public class EdgeContextComponent {
@Autowired
private ActorService actorService;
@Lazy
@Autowired
private WidgetsBundleService widgetsBundleService;
@Lazy
@Autowired
private WidgetTypeService widgetTypeService;
@Lazy
@Autowired
private DeviceStateService deviceStateService;
@ -155,6 +169,10 @@ public class EdgeContextComponent {
@Autowired
private DashboardUpdateMsgConstructor dashboardUpdateMsgConstructor;
@Lazy
@Autowired
private CustomerUpdateMsgConstructor customerUpdateMsgConstructor;
@Lazy
@Autowired
private UserUpdateMsgConstructor userUpdateMsgConstructor;
@ -163,6 +181,18 @@ public class EdgeContextComponent {
@Autowired
private RelationUpdateMsgConstructor relationUpdateMsgConstructor;
@Lazy
@Autowired
private WidgetsBundleUpdateMsgConstructor widgetsBundleUpdateMsgConstructor;
@Lazy
@Autowired
private WidgetTypeUpdateMsgConstructor widgetTypeUpdateMsgConstructor;
@Lazy
@Autowired
private AdminSettingsUpdateMsgConstructor adminSettingsUpdateMsgConstructor;
@Lazy
@Autowired
private EntityDataMsgConstructor entityDataMsgConstructor;

788
application/src/main/java/org/thingsboard/server/service/edge/rpc/EdgeGrpcSession.java

File diff suppressed because it is too large

41
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/AdminSettingsUpdateMsgConstructor.java

@ -0,0 +1,41 @@
/**
* Copyright © 2016-2020 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.service.edge.rpc.constructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.id.AdminSettingsId;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import org.thingsboard.server.gen.edge.AdminSettingsUpdateMsg;
@Slf4j
@Component
public class AdminSettingsUpdateMsgConstructor {
public AdminSettingsUpdateMsg constructAdminSettingsUpdateMsg(AdminSettings adminSettings) {
AdminSettingsUpdateMsg.Builder builder = AdminSettingsUpdateMsg.newBuilder()
.setKey(adminSettings.getKey())
.setJsonValue(JacksonUtil.toString(adminSettings.getJsonValue()));
AdminSettingsId adminSettingsId = adminSettings.getId();
if (adminSettingsId != null) {
builder.setIdMSB(adminSettingsId.getId().getMostSignificantBits());
builder.setIdLSB(adminSettingsId.getId().getLeastSignificantBits());
}
return builder.build();
}
}

72
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/CustomerUpdateMsgConstructor.java

@ -0,0 +1,72 @@
/**
* Copyright © 2016-2020 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.service.edge.rpc.constructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import org.thingsboard.server.gen.edge.CustomerUpdateMsg;
import org.thingsboard.server.gen.edge.UpdateMsgType;
@Component
@Slf4j
public class CustomerUpdateMsgConstructor {
public CustomerUpdateMsg constructCustomerUpdatedMsg(UpdateMsgType msgType, Customer customer) {
CustomerUpdateMsg.Builder builder = CustomerUpdateMsg.newBuilder()
.setMsgType(msgType)
.setIdMSB(customer.getId().getId().getMostSignificantBits())
.setIdLSB(customer.getId().getId().getLeastSignificantBits())
.setTitle(customer.getTitle());
if (customer.getCountry() != null) {
builder.setCountry(customer.getCountry());
}
if (customer.getState() != null) {
builder.setState(customer.getState());
}
if (customer.getCity() != null) {
builder.setCity(customer.getCity());
}
if (customer.getAddress() != null) {
builder.setAddress(customer.getAddress());
}
if (customer.getAddress2() != null) {
builder.setAddress2(customer.getAddress2());
}
if (customer.getZip() != null) {
builder.setZip(customer.getZip());
}
if (customer.getPhone() != null) {
builder.setPhone(customer.getPhone());
}
if (customer.getEmail() != null) {
builder.setEmail(customer.getEmail());
}
if (customer.getAdditionalInfo() != null) {
builder.setAdditionalInfo(JacksonUtil.toString(customer.getAdditionalInfo()));
}
return builder.build();
}
public CustomerUpdateMsg constructCustomerDeleteMsg(CustomerId customerId) {
return CustomerUpdateMsg.newBuilder()
.setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
.setIdMSB(customerId.getId().getMostSignificantBits())
.setIdLSB(customerId.getId().getLeastSignificantBits()).build();
}
}

8
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/EntityDataMsgConstructor.java

@ -18,6 +18,7 @@ package org.thingsboard.server.service.edge.rpc.constructor;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -41,7 +42,12 @@ public class EntityDataMsgConstructor {
switch (actionType) {
case TIMESERIES_UPDATED:
try {
builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(entityData));
JsonObject data = entityData.getAsJsonObject();
long ts = System.currentTimeMillis();
if (data.get("ts") != null && !data.get("ts").isJsonNull()) {
ts = data.getAsJsonObject("ts").getAsLong();
}
builder.setPostTelemetryMsg(JsonConverter.convertToTelemetryProto(data.getAsJsonObject("data"), ts));
} catch (Exception e) {
log.warn("Can't convert to telemetry proto, entityData [{}]", entityData, e);
}

4
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/UserUpdateMsgConstructor.java

@ -36,6 +36,10 @@ public class UserUpdateMsgConstructor {
.setIdLSB(user.getId().getId().getLeastSignificantBits())
.setEmail(user.getEmail())
.setAuthority(user.getAuthority().name());
if (user.getCustomerId() != null) {
builder.setCustomerIdMSB(user.getCustomerId().getId().getMostSignificantBits());
builder.setCustomerIdLSB(user.getCustomerId().getId().getLeastSignificantBits());
}
if (user.getFirstName() != null) {
builder.setFirstName(user.getFirstName());
}

61
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetTypeUpdateMsgConstructor.java

@ -0,0 +1,61 @@
/**
* Copyright © 2016-2020 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.service.edge.rpc.constructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetTypeId;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import org.thingsboard.server.gen.edge.UpdateMsgType;
import org.thingsboard.server.gen.edge.WidgetTypeUpdateMsg;
@Component
@Slf4j
public class WidgetTypeUpdateMsgConstructor {
public WidgetTypeUpdateMsg constructWidgetTypeUpdateMsg(UpdateMsgType msgType, WidgetType widgetType) {
WidgetTypeUpdateMsg.Builder builder = WidgetTypeUpdateMsg.newBuilder()
.setMsgType(msgType)
.setIdMSB(widgetType.getId().getId().getMostSignificantBits())
.setIdLSB(widgetType.getId().getId().getLeastSignificantBits());
if (widgetType.getBundleAlias() != null) {
builder.setBundleAlias(widgetType.getBundleAlias());
}
if (widgetType.getAlias() != null) {
builder.setAlias(widgetType.getAlias());
}
if (widgetType.getName() != null) {
builder.setName(widgetType.getName());
}
if (widgetType.getDescriptor() != null) {
builder.setDescriptorJson(JacksonUtil.toString(widgetType.getDescriptor()));
}
if (widgetType.getTenantId().equals(TenantId.SYS_TENANT_ID)) {
builder.setIsSystem(true);
}
return builder.build();
}
public WidgetTypeUpdateMsg constructWidgetTypeDeleteMsg(WidgetTypeId widgetTypeId) {
return WidgetTypeUpdateMsg.newBuilder()
.setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
.setIdMSB(widgetTypeId.getId().getMostSignificantBits())
.setIdLSB(widgetTypeId.getId().getLeastSignificantBits())
.build();
}
}

54
application/src/main/java/org/thingsboard/server/service/edge/rpc/constructor/WidgetsBundleUpdateMsgConstructor.java

@ -0,0 +1,54 @@
/**
* Copyright © 2016-2020 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.service.edge.rpc.constructor;
import com.google.protobuf.ByteString;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.WidgetsBundleId;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.gen.edge.UpdateMsgType;
import org.thingsboard.server.gen.edge.WidgetsBundleUpdateMsg;
@Component
@Slf4j
public class WidgetsBundleUpdateMsgConstructor {
public WidgetsBundleUpdateMsg constructWidgetsBundleUpdateMsg(UpdateMsgType msgType, WidgetsBundle widgetsBundle) {
WidgetsBundleUpdateMsg.Builder builder = WidgetsBundleUpdateMsg.newBuilder()
.setMsgType(msgType)
.setIdMSB(widgetsBundle.getId().getId().getMostSignificantBits())
.setIdLSB(widgetsBundle.getId().getId().getLeastSignificantBits())
.setTitle(widgetsBundle.getTitle())
.setAlias(widgetsBundle.getAlias());
if (widgetsBundle.getImage() != null) {
builder.setImage(ByteString.copyFrom(widgetsBundle.getImage()));
}
if (widgetsBundle.getTenantId().equals(TenantId.SYS_TENANT_ID)) {
builder.setIsSystem(true);
}
return builder.build();
}
public WidgetsBundleUpdateMsg constructWidgetsBundleDeleteMsg(WidgetsBundleId widgetsBundleId) {
return WidgetsBundleUpdateMsg.newBuilder()
.setMsgType(UpdateMsgType.ENTITY_DELETED_RPC_MESSAGE)
.setIdMSB(widgetsBundleId.getId().getMostSignificantBits())
.setIdLSB(widgetsBundleId.getId().getLeastSignificantBits())
.build();
}
}

187
application/src/main/java/org/thingsboard/server/service/edge/rpc/init/DefaultSyncEdgeService.java

@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.DashboardInfo;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
@ -54,6 +55,8 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
import org.thingsboard.server.common.data.relation.EntitySearchDirection;
import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.widget.WidgetType;
import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.attributes.AttributesService;
import org.thingsboard.server.dao.dashboard.DashboardService;
@ -62,7 +65,10 @@ import org.thingsboard.server.dao.edge.EdgeEventService;
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.settings.AdminSettingsService;
import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.dao.widget.WidgetTypeService;
import org.thingsboard.server.dao.widget.WidgetsBundleService;
import org.thingsboard.server.gen.edge.AttributesRequestMsg;
import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg;
import org.thingsboard.server.gen.edge.RelationRequestMsg;
@ -109,6 +115,15 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
@Autowired
private UserService userService;
@Autowired
private WidgetsBundleService widgetsBundleService;
@Autowired
private WidgetTypeService widgetTypeService;
@Autowired
private AdminSettingsService adminSettingsService;
@Autowired
private DbCallbackExecutorService dbCallbackExecutorService;
@ -121,6 +136,8 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
syncAssets(edge);
syncEntityViews(edge);
syncDashboards(edge);
syncWidgetsBundleAndWidgetTypes(edge);
syncAdminSettings(edge);
} catch (Exception e) {
log.error("Exception during sync process", e);
}
@ -253,6 +270,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
TextPageData<User> pageData = userService.findTenantAdmins(edge.getTenantId(), new TextPageLink(Integer.MAX_VALUE));
pushUsersToEdge(pageData, edge);
if (edge.getCustomerId() != null && !EntityId.NULL_UUID.equals(edge.getCustomerId().getId())) {
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.CUSTOMER, ActionType.ADDED, edge.getCustomerId(), null);
pageData = userService.findCustomerUsers(edge.getTenantId(), edge.getCustomerId(), new TextPageLink(Integer.MAX_VALUE));
pushUsersToEdge(pageData, edge);
}
@ -261,6 +279,33 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
}
}
private void syncWidgetsBundleAndWidgetTypes(Edge edge) {
List<WidgetsBundle> widgetsBundlesToPush = new ArrayList<>();
List<WidgetType> widgetTypesToPush = new ArrayList<>();
widgetsBundlesToPush.addAll(widgetsBundleService.findAllTenantWidgetsBundlesByTenantId(edge.getTenantId()));
widgetsBundlesToPush.addAll(widgetsBundleService.findSystemWidgetsBundles(edge.getTenantId()));
try {
for (WidgetsBundle widgetsBundle: widgetsBundlesToPush) {
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.WIDGETS_BUNDLE, ActionType.ADDED, widgetsBundle.getId(), null);
widgetTypesToPush.addAll(widgetTypeService.findWidgetTypesByTenantIdAndBundleAlias(widgetsBundle.getTenantId(), widgetsBundle.getAlias()));
}
for (WidgetType widgetType: widgetTypesToPush) {
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.WIDGET_TYPE, ActionType.ADDED, widgetType.getId(), null);
}
} catch (Exception e) {
log.error("Exception during loading widgets bundle(s) and widget type(s) on sync!", e);
}
}
private void syncAdminSettings(Edge edge) {
try {
AdminSettings mailSettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "mail");
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.ADMIN_SETTINGS, ActionType.UPDATED, null, mapper.valueToTree(mailSettings));
} catch (Exception e) {
log.error("Can't load admin settings", e);
}
}
private void pushUsersToEdge(TextPageData<User> pageData, Edge edge) {
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
log.trace("[{}] [{}] user(s) are going to be pushed to edge.", edge.getId(), pageData.getData().size());
@ -271,64 +316,62 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
}
@Override
public void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) {
public ListenableFuture<Void> processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg) {
if (ruleChainMetadataRequestMsg.getRuleChainIdMSB() != 0 && ruleChainMetadataRequestMsg.getRuleChainIdLSB() != 0) {
RuleChainId ruleChainId = new RuleChainId(new UUID(ruleChainMetadataRequestMsg.getRuleChainIdMSB(), ruleChainMetadataRequestMsg.getRuleChainIdLSB()));
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, ActionType.ADDED, ruleChainId, null);
ListenableFuture<EdgeEvent> future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.RULE_CHAIN_METADATA, ActionType.ADDED, ruleChainId, null);
return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService);
}
return Futures.immediateFuture(null);
}
@Override
public void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg) {
public ListenableFuture<Void> processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg) {
EntityId entityId = EntityIdFactory.getByTypeAndUuid(
EntityType.valueOf(attributesRequestMsg.getEntityType()),
new UUID(attributesRequestMsg.getEntityIdMSB(), attributesRequestMsg.getEntityIdLSB()));
final EdgeEventType edgeEventType = getEdgeQueueTypeByEntityType(entityId.getEntityType());
if (edgeEventType != null) {
ListenableFuture<List<AttributeKvEntry>> ssAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SERVER_SCOPE);
Futures.addCallback(ssAttrFuture, new FutureCallback<List<AttributeKvEntry>>() {
@Override
public void onSuccess(@Nullable List<AttributeKvEntry> ssAttributes) {
if (ssAttributes != null && !ssAttributes.isEmpty()) {
try {
Map<String, Object> entityData = new HashMap<>();
ObjectNode attributes = mapper.createObjectNode();
for (AttributeKvEntry attr : ssAttributes) {
if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) {
attributes.put(attr.getKey(), attr.getBooleanValue().get());
} else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) {
attributes.put(attr.getKey(), attr.getDoubleValue().get());
} else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) {
attributes.put(attr.getKey(), attr.getLongValue().get());
} else {
attributes.put(attr.getKey(), attr.getValueAsString());
}
return Futures.transform(ssAttrFuture, ssAttributes -> {
if (ssAttributes != null && !ssAttributes.isEmpty()) {
try {
Map<String, Object> entityData = new HashMap<>();
ObjectNode attributes = mapper.createObjectNode();
for (AttributeKvEntry attr : ssAttributes) {
if (attr.getDataType() == DataType.BOOLEAN && attr.getBooleanValue().isPresent()) {
attributes.put(attr.getKey(), attr.getBooleanValue().get());
} else if (attr.getDataType() == DataType.DOUBLE && attr.getDoubleValue().isPresent()) {
attributes.put(attr.getKey(), attr.getDoubleValue().get());
} else if (attr.getDataType() == DataType.LONG && attr.getLongValue().isPresent()) {
attributes.put(attr.getKey(), attr.getLongValue().get());
} else {
attributes.put(attr.getKey(), attr.getValueAsString());
}
entityData.put("kv", attributes);
entityData.put("scope", DataConstants.SERVER_SCOPE);
JsonNode entityBody = mapper.valueToTree(entityData);
log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody);
saveEdgeEvent(edge.getTenantId(),
edge.getId(),
edgeEventType,
ActionType.ATTRIBUTES_UPDATED,
entityId,
entityBody);
} catch (Exception e) {
log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e);
}
entityData.put("kv", attributes);
entityData.put("scope", DataConstants.SERVER_SCOPE);
JsonNode entityBody = mapper.valueToTree(entityData);
log.debug("Sending attributes data msg, entityId [{}], attributes [{}]", entityId, entityBody);
saveEdgeEvent(edge.getTenantId(),
edge.getId(),
edgeEventType,
ActionType.ATTRIBUTES_UPDATED,
entityId,
entityBody);
} catch (Exception e) {
log.error("[{}] Failed to send attribute updates to the edge", edge.getName(), e);
throw new RuntimeException("[" + edge.getName() + "] Failed to send attribute updates to the edge", e);
}
}
@Override
public void onFailure(Throwable t) {
}
return null;
}, dbCallbackExecutorService);
// TODO: voba - push shared attributes to edge?
ListenableFuture<List<AttributeKvEntry>> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE);
ListenableFuture<List<AttributeKvEntry>> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE);
// ListenableFuture<List<AttributeKvEntry>> shAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.SHARED_SCOPE);
// ListenableFuture<List<AttributeKvEntry>> clAttrFuture = attributesService.findAll(edge.getTenantId(), entityId, DataConstants.CLIENT_SCOPE);
} else {
return Futures.immediateFuture(null);
}
}
@ -346,7 +389,7 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
}
@Override
public void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg) {
public ListenableFuture<Void> processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg) {
EntityId entityId = EntityIdFactory.getByTypeAndUuid(
EntityType.valueOf(relationRequestMsg.getEntityType()),
new UUID(relationRequestMsg.getEntityIdMSB(), relationRequestMsg.getEntityIdLSB()));
@ -355,39 +398,33 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.FROM));
futures.add(findRelationByQuery(edge, entityId, EntitySearchDirection.TO));
ListenableFuture<List<List<EntityRelation>>> relationsListFuture = Futures.allAsList(futures);
Futures.addCallback(relationsListFuture, new FutureCallback<List<List<EntityRelation>>>() {
@Override
public void onSuccess(@Nullable List<List<EntityRelation>> relationsList) {
try {
if (!relationsList.isEmpty()) {
for (List<EntityRelation> entityRelations : relationsList) {
log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size());
for (EntityRelation relation : entityRelations) {
try {
if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) &&
!relation.getTo().getEntityType().equals(EntityType.EDGE)) {
saveEdgeEvent(edge.getTenantId(),
edge.getId(),
EdgeEventType.RELATION,
ActionType.ADDED,
null,
mapper.valueToTree(relation));
}
} catch (Exception e) {
log.error("Exception during loading relation [{}] to edge on sync!", relation, e);
return Futures.transform(relationsListFuture, relationsList -> {
try {
if (relationsList != null && !relationsList.isEmpty()) {
for (List<EntityRelation> entityRelations : relationsList) {
log.trace("[{}] [{}] [{}] relation(s) are going to be pushed to edge.", edge.getId(), entityId, entityRelations.size());
for (EntityRelation relation : entityRelations) {
try {
if (!relation.getFrom().getEntityType().equals(EntityType.EDGE) &&
!relation.getTo().getEntityType().equals(EntityType.EDGE)) {
saveEdgeEvent(edge.getTenantId(),
edge.getId(),
EdgeEventType.RELATION,
ActionType.ADDED,
null,
mapper.valueToTree(relation));
}
} catch (Exception e) {
log.error("Exception during loading relation [{}] to edge on sync!", relation, e);
}
}
}
} catch (Exception e) {
log.error("Exception during loading relation(s) to edge on sync!", e);
}
} catch (Exception e) {
log.error("Exception during loading relation(s) to edge on sync!", e);
throw new RuntimeException("Exception during loading relation(s) to edge on sync!", e);
}
@Override
public void onFailure(Throwable t) {
log.error("Exception during loading relation(s) to edge on sync!", t);
}
return null;
}, dbCallbackExecutorService);
}
@ -398,22 +435,26 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
}
@Override
public void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) {
public ListenableFuture<Void> processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg) {
if (deviceCredentialsRequestMsg.getDeviceIdMSB() != 0 && deviceCredentialsRequestMsg.getDeviceIdLSB() != 0) {
DeviceId deviceId = new DeviceId(new UUID(deviceCredentialsRequestMsg.getDeviceIdMSB(), deviceCredentialsRequestMsg.getDeviceIdLSB()));
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED, deviceId, null);
ListenableFuture<EdgeEvent> future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.DEVICE, ActionType.CREDENTIALS_UPDATED, deviceId, null);
return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService);
}
return Futures.immediateFuture(null);
}
@Override
public void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) {
public ListenableFuture<Void> processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg) {
if (userCredentialsRequestMsg.getUserIdMSB() != 0 && userCredentialsRequestMsg.getUserIdLSB() != 0) {
UserId userId = new UserId(new UUID(userCredentialsRequestMsg.getUserIdMSB(), userCredentialsRequestMsg.getUserIdLSB()));
saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED, userId, null);
ListenableFuture<EdgeEvent> future = saveEdgeEvent(edge.getTenantId(), edge.getId(), EdgeEventType.USER, ActionType.CREDENTIALS_UPDATED, userId, null);
return Futures.transform(future, edgeEvent -> null, dbCallbackExecutorService);
}
return Futures.immediateFuture(null);
}
private void saveEdgeEvent(TenantId tenantId,
private ListenableFuture<EdgeEvent> saveEdgeEvent(TenantId tenantId,
EdgeId edgeId,
EdgeEventType edgeEventType,
ActionType edgeEventAction,
@ -431,6 +472,6 @@ public class DefaultSyncEdgeService implements SyncEdgeService {
edgeEvent.setEntityId(entityId.getId());
}
edgeEvent.setEntityBody(entityBody);
edgeEventService.saveAsync(edgeEvent);
return edgeEventService.saveAsync(edgeEvent);
}
}

11
application/src/main/java/org/thingsboard/server/service/edge/rpc/init/SyncEdgeService.java

@ -15,6 +15,7 @@
*/
package org.thingsboard.server.service.edge.rpc.init;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.gen.edge.AttributesRequestMsg;
import org.thingsboard.server.gen.edge.DeviceCredentialsRequestMsg;
@ -26,13 +27,13 @@ public interface SyncEdgeService {
void sync(Edge edge);
void processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg);
ListenableFuture<Void> processRuleChainMetadataRequestMsg(Edge edge, RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg);
void processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg);
ListenableFuture<Void> processAttributesRequestMsg(Edge edge, AttributesRequestMsg attributesRequestMsg);
void processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg);
ListenableFuture<Void> processRelationRequestMsg(Edge edge, RelationRequestMsg relationRequestMsg);
void processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg);
ListenableFuture<Void> processDeviceCredentialsRequestMsg(Edge edge, DeviceCredentialsRequestMsg deviceCredentialsRequestMsg);
void processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg);
ListenableFuture<Void> processUserCredentialsRequestMsg(Edge edge, UserCredentialsRequestMsg userCredentialsRequestMsg);
}

56
application/src/main/java/org/thingsboard/server/service/ttl/edge/EdgeEventsCleanUpService.java

@ -0,0 +1,56 @@
/**
* Copyright © 2016-2020 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.service.ttl.edge;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.thingsboard.server.dao.util.PsqlDao;
import org.thingsboard.server.service.ttl.AbstractCleanUpService;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
@PsqlDao
@Slf4j
@Service
public class EdgeEventsCleanUpService extends AbstractCleanUpService {
@Value("${sql.ttl.edge_events.edge_events_ttl}")
private long ttl;
@Value("${sql.ttl.edge_events.enabled}")
private boolean ttlTaskExecutionEnabled;
@Scheduled(initialDelayString = "${sql.ttl.edge_events.execution_interval_ms}", fixedDelayString = "${sql.ttl.edge_events.execution_interval_ms}")
public void cleanUp() {
if (ttlTaskExecutionEnabled) {
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
doCleanUp(conn);
} catch (SQLException e) {
log.error("SQLException occurred during TTL task execution ", e);
}
}
}
@Override
protected void doCleanUp(Connection connection) {
long totalEdgeEventsRemoved = executeQuery(connection, "call cleanup_edge_events_by_ttl(" + ttl + ", 0);");
log.info("Total edge events removed by TTL: [{}]", totalEdgeEventsRemoved);
}
}

4
application/src/main/resources/thingsboard.yml

@ -282,6 +282,10 @@ sql:
execution_interval_ms: "${SQL_TTL_EVENTS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day
events_ttl: "${SQL_TTL_EVENTS_EVENTS_TTL:0}" # Number of seconds
debug_events_ttl: "${SQL_TTL_EVENTS_DEBUG_EVENTS_TTL:604800}" # Number of seconds. The current value corresponds to one week
edge_events:
enabled: "${SQL_TTL_EDGE_EVENTS_ENABLED:true}"
execution_interval_ms: "${SQL_TTL_EDGE_EVENTS_EXECUTION_INTERVAL:86400000}" # Number of milliseconds. The current value corresponds to one day
edge_events_ttl: "${SQL_TTL_EDGE_EVENTS_TTL:2628000}" # Number of seconds. The current value corresponds to one month
# Actor system parameters
actors:

13
common/data/src/main/java/org/thingsboard/server/common/data/EdgeUtils.java

@ -16,9 +16,6 @@
package org.thingsboard.server.common.data;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeId;
import java.util.Set;
public final class EdgeUtils {
@ -37,8 +34,18 @@ public final class EdgeUtils {
return EdgeEventType.DASHBOARD;
case USER:
return EdgeEventType.USER;
case RULE_CHAIN:
return EdgeEventType.RULE_CHAIN;
case ALARM:
return EdgeEventType.ALARM;
case TENANT:
return EdgeEventType.TENANT;
case CUSTOMER:
return EdgeEventType.CUSTOMER;
case WIDGETS_BUNDLE:
return EdgeEventType.WIDGETS_BUNDLE;
case WIDGET_TYPE:
return EdgeEventType.WIDGET_TYPE;
default:
return null;
}

6
common/data/src/main/java/org/thingsboard/server/common/data/edge/EdgeEventType.java

@ -26,5 +26,9 @@ public enum EdgeEventType {
EDGE,
USER,
CUSTOMER,
RELATION
RELATION,
TENANT,
WIDGETS_BUNDLE,
WIDGET_TYPE,
ADMIN_SETTINGS
}

4
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java

@ -87,6 +87,10 @@ public class EntityIdFactory {
return new RuleChainId(uuid);
case ENTITY_VIEW:
return new EntityViewId(uuid);
case WIDGETS_BUNDLE:
return new WidgetsBundleId(uuid);
case WIDGET_TYPE:
return new WidgetTypeId(uuid);
case EDGE:
return new EdgeId(uuid);
}

38
common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeGrpcClient.java

@ -28,9 +28,9 @@ import org.thingsboard.server.gen.edge.ConnectRequestMsg;
import org.thingsboard.server.gen.edge.ConnectResponseCode;
import org.thingsboard.server.gen.edge.ConnectResponseMsg;
import org.thingsboard.server.gen.edge.DownlinkMsg;
import org.thingsboard.server.gen.edge.DownlinkResponseMsg;
import org.thingsboard.server.gen.edge.EdgeConfiguration;
import org.thingsboard.server.gen.edge.EdgeRpcServiceGrpc;
import org.thingsboard.server.gen.edge.EntityUpdateMsg;
import org.thingsboard.server.gen.edge.RequestMsg;
import org.thingsboard.server.gen.edge.RequestMsgType;
import org.thingsboard.server.gen.edge.ResponseMsg;
@ -41,6 +41,7 @@ import javax.net.ssl.SSLException;
import java.io.File;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
@Service
@ -62,12 +63,13 @@ public class EdgeGrpcClient implements EdgeRpcClient {
private StreamObserver<RequestMsg> inputStream;
private static final ReentrantLock uplinkMsgLock = new ReentrantLock();
@Override
public void connect(String edgeKey,
String edgeSecret,
Consumer<UplinkResponseMsg> onUplinkResponse,
Consumer<EdgeConfiguration> onEdgeUpdate,
Consumer<EntityUpdateMsg> onEntityUpdate,
Consumer<DownlinkMsg> onDownlink,
Consumer<Exception> onError) {
NettyChannelBuilder builder = NettyChannelBuilder.forAddress(rpcHost, rpcPort).usePlaintext();
@ -83,7 +85,7 @@ public class EdgeGrpcClient implements EdgeRpcClient {
channel = builder.build();
EdgeRpcServiceGrpc.EdgeRpcServiceStub stub = EdgeRpcServiceGrpc.newStub(channel);
log.info("[{}] Sending a connect request to the TB!", edgeKey);
this.inputStream = stub.handleMsgs(initOutputStream(edgeKey, onUplinkResponse, onEdgeUpdate, onEntityUpdate, onDownlink, onError));
this.inputStream = stub.handleMsgs(initOutputStream(edgeKey, onUplinkResponse, onEdgeUpdate, onDownlink, onError));
this.inputStream.onNext(RequestMsg.newBuilder()
.setMsgType(RequestMsgType.CONNECT_RPC_MESSAGE)
.setConnectRequestMsg(ConnectRequestMsg.newBuilder().setEdgeRoutingKey(edgeKey).setEdgeSecret(edgeSecret).build())
@ -110,16 +112,33 @@ public class EdgeGrpcClient implements EdgeRpcClient {
@Override
public void sendUplinkMsg(UplinkMsg msg) {
this.inputStream.onNext(RequestMsg.newBuilder()
.setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE)
.setUplinkMsg(msg)
.build());
try {
uplinkMsgLock.lock();
this.inputStream.onNext(RequestMsg.newBuilder()
.setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE)
.setUplinkMsg(msg)
.build());
} finally {
uplinkMsgLock.unlock();
}
}
@Override
public void sendDownlinkResponseMsg(DownlinkResponseMsg downlinkResponseMsg) {
try {
uplinkMsgLock.lock();
this.inputStream.onNext(RequestMsg.newBuilder()
.setMsgType(RequestMsgType.UPLINK_RPC_MESSAGE)
.setDownlinkResponseMsg(downlinkResponseMsg)
.build());
} finally {
uplinkMsgLock.unlock();
}
}
private StreamObserver<ResponseMsg> initOutputStream(String edgeKey,
Consumer<UplinkResponseMsg> onUplinkResponse,
Consumer<EdgeConfiguration> onEdgeUpdate,
Consumer<EntityUpdateMsg> onEntityUpdate,
Consumer<DownlinkMsg> onDownlink,
Consumer<Exception> onError) {
return new StreamObserver<ResponseMsg>() {
@ -137,9 +156,6 @@ public class EdgeGrpcClient implements EdgeRpcClient {
} else if (responseMsg.hasUplinkResponseMsg()) {
log.debug("[{}] Uplink response message received {}", edgeKey, responseMsg.getUplinkResponseMsg());
onUplinkResponse.accept(responseMsg.getUplinkResponseMsg());
} else if (responseMsg.hasEntityUpdateMsg()) {
log.debug("[{}] Entity update message received {}", edgeKey, responseMsg.getEntityUpdateMsg());
onEntityUpdate.accept(responseMsg.getEntityUpdateMsg());
} else if (responseMsg.hasDownlinkMsg()) {
log.debug("[{}] Downlink message received {}", edgeKey, responseMsg.getDownlinkMsg());
onDownlink.accept(responseMsg.getDownlinkMsg());

7
common/edge-api/src/main/java/org/thingsboard/edge/rpc/EdgeRpcClient.java

@ -16,8 +16,8 @@
package org.thingsboard.edge.rpc;
import org.thingsboard.server.gen.edge.DownlinkMsg;
import org.thingsboard.server.gen.edge.DownlinkResponseMsg;
import org.thingsboard.server.gen.edge.EdgeConfiguration;
import org.thingsboard.server.gen.edge.EntityUpdateMsg;
import org.thingsboard.server.gen.edge.UplinkMsg;
import org.thingsboard.server.gen.edge.UplinkResponseMsg;
@ -29,11 +29,12 @@ public interface EdgeRpcClient {
String integrationSecret,
Consumer<UplinkResponseMsg> onUplinkResponse,
Consumer<EdgeConfiguration> onEdgeUpdate,
Consumer<EntityUpdateMsg> onEntityUpdate,
Consumer<DownlinkMsg> onDownlink,
Consumer<Exception> onError);
void disconnect() throws InterruptedException;
void sendUplinkMsg(UplinkMsg uplinkMsg) throws InterruptedException;
void sendUplinkMsg(UplinkMsg uplinkMsg);
void sendDownlinkResponseMsg(DownlinkResponseMsg downlinkResponseMsg);
}

91
common/edge-api/src/main/proto/edge.proto

@ -37,28 +37,13 @@ message RequestMsg {
RequestMsgType msgType = 1;
ConnectRequestMsg connectRequestMsg = 2;
UplinkMsg uplinkMsg = 3;
DownlinkResponseMsg downlinkResponseMsg = 4;
}
message ResponseMsg {
ConnectResponseMsg connectResponseMsg = 1;
UplinkResponseMsg uplinkResponseMsg = 2;
EntityUpdateMsg entityUpdateMsg = 3;
DownlinkMsg downlinkMsg = 4;
}
message EntityUpdateMsg {
DeviceUpdateMsg deviceUpdateMsg = 1;
DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 2;
RuleChainUpdateMsg ruleChainUpdateMsg = 3;
RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 4;
DashboardUpdateMsg dashboardUpdateMsg = 5;
AssetUpdateMsg assetUpdateMsg = 6;
EntityViewUpdateMsg entityViewUpdateMsg = 7;
AlarmUpdateMsg alarmUpdateMsg = 8;
UserUpdateMsg userUpdateMsg = 9;
UserCredentialsUpdateMsg userCredentialsUpdateMsg = 10;
CustomerUpdateMsg customerUpdateMsg = 11;
RelationUpdateMsg relationUpdateMsg = 12;
DownlinkMsg downlinkMsg = 3;
}
enum RequestMsgType {
@ -259,11 +244,41 @@ message UserUpdateMsg {
UpdateMsgType msgType = 1;
int64 idMSB = 2;
int64 idLSB = 3;
string email = 4;
string authority = 5;
string firstName = 6;
string lastName = 7;
string additionalInfo = 8;
int64 customerIdMSB = 4;
int64 customerIdLSB = 5;
string email = 6;
string authority = 7;
string firstName = 8;
string lastName = 9;
string additionalInfo = 10;
}
message WidgetsBundleUpdateMsg {
UpdateMsgType msgType = 1;
int64 idMSB = 2;
int64 idLSB = 3;
string title = 4;
string alias = 5;
bytes image = 6;
bool isSystem = 7;
}
message WidgetTypeUpdateMsg {
UpdateMsgType msgType = 1;
int64 idMSB = 2;
int64 idLSB = 3;
string bundleAlias = 4;
string alias = 5;
string name = 6;
string descriptorJson = 7;
bool isSystem = 8;
}
message AdminSettingsUpdateMsg {
int64 idMSB = 1;
int64 idLSB = 2;
string key = 3;
string jsonValue = 4;
}
message UserCredentialsUpdateMsg {
@ -315,11 +330,12 @@ message UplinkMsg {
repeated DeviceUpdateMsg deviceUpdateMsg = 3;
repeated DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 4;
repeated AlarmUpdateMsg alarmUpdateMsg = 5;
repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 6;
repeated AttributesRequestMsg attributesRequestMsg = 7;
repeated RelationRequestMsg relationRequestMsg = 8;
repeated UserCredentialsRequestMsg userCredentialsRequestMsg = 9;
repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 10;
repeated RelationUpdateMsg relationUpdateMsg = 6;
repeated RuleChainMetadataRequestMsg ruleChainMetadataRequestMsg = 7;
repeated AttributesRequestMsg attributesRequestMsg = 8;
repeated RelationRequestMsg relationRequestMsg = 9;
repeated UserCredentialsRequestMsg userCredentialsRequestMsg = 10;
repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 11;
}
message UplinkResponseMsg {
@ -327,9 +343,30 @@ message UplinkResponseMsg {
string errorMsg = 2;
}
message DownlinkResponseMsg {
bool success = 1;
string errorMsg = 2;
}
message DownlinkMsg {
int32 downlinkMsgId = 1;
repeated EntityDataProto entityData = 2;
repeated DeviceCredentialsRequestMsg deviceCredentialsRequestMsg = 3;
repeated DeviceUpdateMsg deviceUpdateMsg = 4;
repeated DeviceCredentialsUpdateMsg deviceCredentialsUpdateMsg = 5;
repeated RuleChainUpdateMsg ruleChainUpdateMsg = 6;
repeated RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 7;
repeated DashboardUpdateMsg dashboardUpdateMsg = 8;
repeated AssetUpdateMsg assetUpdateMsg = 9;
repeated EntityViewUpdateMsg entityViewUpdateMsg = 10;
repeated AlarmUpdateMsg alarmUpdateMsg = 11;
repeated UserUpdateMsg userUpdateMsg = 12;
repeated UserCredentialsUpdateMsg userCredentialsUpdateMsg = 13;
repeated CustomerUpdateMsg customerUpdateMsg = 14;
repeated RelationUpdateMsg relationUpdateMsg = 15;
repeated WidgetsBundleUpdateMsg widgetsBundleUpdateMsg = 16;
repeated WidgetTypeUpdateMsg widgetTypeUpdateMsg = 17;
repeated AdminSettingsUpdateMsg adminSettingsUpdateMsg = 18;
}

8
common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/adaptor/JsonConverter.java

@ -68,12 +68,16 @@ public class JsonConverter {
private static int maxStringValueLength = 0;
public static PostTelemetryMsg convertToTelemetryProto(JsonElement jsonElement) throws JsonSyntaxException {
public static PostTelemetryMsg convertToTelemetryProto(JsonElement jsonElement, long ts) throws JsonSyntaxException {
PostTelemetryMsg.Builder builder = PostTelemetryMsg.newBuilder();
convertToTelemetry(jsonElement, System.currentTimeMillis(), null, builder);
convertToTelemetry(jsonElement, ts, null, builder);
return builder.build();
}
public static PostTelemetryMsg convertToTelemetryProto(JsonElement jsonElement) throws JsonSyntaxException {
return convertToTelemetryProto(jsonElement, System.currentTimeMillis());
}
private static void convertToTelemetry(JsonElement jsonElement, long systemTs, Map<Long, List<KvEntry>> result, PostTelemetryMsg.Builder builder) {
if (jsonElement.isJsonObject()) {
parseObject(systemTs, result, builder, jsonElement.getAsJsonObject());

17
dao/src/main/resources/sql/schema-entities.sql

@ -307,3 +307,20 @@ BEGIN
deleted := ttl_deleted_count + debug_ttl_deleted_count;
END
$$;
CREATE OR REPLACE PROCEDURE cleanup_edge_events_by_ttl(IN ttl bigint, INOUT deleted bigint)
LANGUAGE plpgsql AS
$$
DECLARE
ttl_ts bigint;
ttl_deleted_count bigint DEFAULT 0;
BEGIN
IF ttl > 0 THEN
ttl_ts := (EXTRACT(EPOCH FROM current_timestamp) * 1000 - ttl::bigint * 1000)::bigint;
EXECUTE format(
'WITH deleted AS (DELETE FROM edge_event WHERE ts < %L::bigint RETURNING *) SELECT count(*) FROM deleted', ttl_ts) into ttl_deleted_count;
END IF;
RAISE NOTICE 'Edge events removed by ttl: %', ttl_deleted_count;
deleted := ttl_deleted_count;
END
$$;

1
pom.xml

@ -725,6 +725,7 @@
<exclude>**/*.proto.js</exclude>
<exclude>docker/haproxy/**</exclude>
<exclude>docker/tb-node/**</exclude>
<exclude>.run/**</exclude>
</excludes>
<mapping>
<proto>JAVADOC_STYLE</proto>

113
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/TbMsgPushToEdgeNode.java

@ -33,11 +33,15 @@ import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.IdBased;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
@ -46,10 +50,12 @@ import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.session.SessionMsgType;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS;
@ -84,34 +90,38 @@ public class TbMsgPushToEdgeNode implements TbNode {
}
if (isSupportedOriginator(msg.getOriginator().getEntityType())) {
if (isSupportedMsgType(msg.getType())) {
ListenableFuture<EdgeId> getEdgeIdFuture = getEdgeIdByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator());
Futures.addCallback(getEdgeIdFuture, new FutureCallback<EdgeId>() {
ListenableFuture<List<EdgeId>> getEdgeIdsFuture = getEdgeIdsByOriginatorId(ctx, ctx.getTenantId(), msg.getOriginator());
Futures.addCallback(getEdgeIdsFuture, new FutureCallback<List<EdgeId>>() {
@Override
public void onSuccess(@Nullable EdgeId edgeId) {
try {
EdgeEvent edgeEvent = buildEdgeEvent(msg, ctx);
if (edgeEvent == null) {
log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType());
ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'"));
} else {
edgeEvent.setEdgeId(edgeId);
ListenableFuture<EdgeEvent> saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent);
Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {
@Override
public void onSuccess(@Nullable EdgeEvent event) {
ctx.tellNext(msg, SUCCESS);
public void onSuccess(@Nullable List<EdgeId> edgeIds) {
if (edgeIds != null && !edgeIds.isEmpty()) {
for (EdgeId edgeId : edgeIds) {
try {
EdgeEvent edgeEvent = buildEdgeEvent(msg, ctx);
if (edgeEvent == null) {
log.debug("Edge event type is null. Entity Type {}", msg.getOriginator().getEntityType());
ctx.tellFailure(msg, new RuntimeException("Edge event type is null. Entity Type '" + msg.getOriginator().getEntityType() + "'"));
} else {
edgeEvent.setEdgeId(edgeId);
ListenableFuture<EdgeEvent> saveFuture = ctx.getEdgeEventService().saveAsync(edgeEvent);
Futures.addCallback(saveFuture, new FutureCallback<EdgeEvent>() {
@Override
public void onSuccess(@Nullable EdgeEvent event) {
ctx.tellNext(msg, SUCCESS);
}
@Override
public void onFailure(Throwable th) {
log.error("Could not save edge event", th);
ctx.tellFailure(msg, th);
}
}, ctx.getDbCallbackExecutor());
}
@Override
public void onFailure(Throwable th) {
log.error("Could not save edge event", th);
ctx.tellFailure(msg, th);
}
}, ctx.getDbCallbackExecutor());
} catch (JsonProcessingException e) {
log.error("Failed to build edge event", e);
ctx.tellFailure(msg, e);
}
}
} catch (JsonProcessingException e) {
log.error("Failed to build edge event", e);
ctx.tellFailure(msg, e);
}
}
@ -140,13 +150,7 @@ public class TbMsgPushToEdgeNode implements TbNode {
return null;
}
ActionType actionType = getActionTypeByMsgType(msg.getType());
JsonNode entityBody = null;
JsonNode data = json.readTree(msg.getData());
if (actionType.equals(ActionType.ATTRIBUTES_UPDATED) || actionType.equals(ActionType.ATTRIBUTES_DELETED)) {
entityBody = getAttributeEntityBody(actionType, data, msg.getMetaData().getData());
} else {
entityBody = data;
}
JsonNode entityBody = getEntityBody(actionType, msg.getData(), msg.getMetaData().getData());
return buildEdgeEvent(ctx.getTenantId(), actionType, msg.getOriginator().getId(), edgeEventTypeByEntityType, entityBody);
}
}
@ -161,19 +165,25 @@ public class TbMsgPushToEdgeNode implements TbNode {
return edgeEvent;
}
private JsonNode getAttributeEntityBody(ActionType actionType, JsonNode data, Map<String, String> metadata) throws JsonProcessingException {
Map<String, Object> entityData = new HashMap<>();
private JsonNode getEntityBody(ActionType actionType, String data, Map<String, String> metadata) throws JsonProcessingException {
Map<String, Object> entityBody = new HashMap<>();
JsonNode dataJson = json.readTree(data);
switch (actionType) {
case ATTRIBUTES_UPDATED:
entityData.put("kv", data);
entityBody.put("kv", dataJson);
entityBody.put("scope", metadata.get("scope"));
break;
case ATTRIBUTES_DELETED:
List<String> keys = json.treeToValue(data.get("attributes"), List.class);
entityData.put("keys", keys);
List<String> keys = json.treeToValue(dataJson.get("attributes"), List.class);
entityBody.put("keys", keys);
entityBody.put("scope", metadata.get("scope"));
break;
case TIMESERIES_UPDATED:
entityBody.put("data", dataJson);
entityBody.put("ts", metadata.get("ts"));
break;
}
entityData.put("scope", metadata.get("scope"));
return json.valueToTree(entityData);
return json.valueToTree(entityBody);
}
private UUID getUUIDFromMsgData(TbMsg msg) throws JsonProcessingException {
@ -201,6 +211,8 @@ public class TbMsgPushToEdgeNode implements TbNode {
case ASSET:
case ENTITY_VIEW:
case DASHBOARD:
case TENANT:
case CUSTOMER:
return true;
default:
return false;
@ -215,15 +227,20 @@ public class TbMsgPushToEdgeNode implements TbNode {
|| DataConstants.ALARM.equals(msgType);
}
private ListenableFuture<EdgeId> getEdgeIdByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) {
ListenableFuture<List<EntityRelation>> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
return Futures.transform(future, relations -> {
if (relations != null && relations.size() > 0) {
return new EdgeId(relations.get(0).getFrom().getId());
} else {
return null;
}
}, ctx.getDbCallbackExecutor());
private ListenableFuture<List<EdgeId>> getEdgeIdsByOriginatorId(TbContext ctx, TenantId tenantId, EntityId originatorId) {
if (EntityType.TENANT.equals(originatorId.getEntityType())) {
TextPageData<Edge> edgesByTenantId = ctx.getEdgeService().findEdgesByTenantId(tenantId, new TextPageLink(Integer.MAX_VALUE));
return Futures.immediateFuture(edgesByTenantId.getData().stream().map(IdBased::getId).collect(Collectors.toList()));
} else {
ListenableFuture<List<EntityRelation>> future = ctx.getRelationService().findByToAndTypeAsync(tenantId, originatorId, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.EDGE);
return Futures.transform(future, relations -> {
List<EdgeId> result = new ArrayList<>();
if (relations != null && relations.size() > 0) {
result.add(new EdgeId(relations.get(0).getFrom().getId()));
}
return result;
}, ctx.getDbCallbackExecutor());
}
}
@Override

Loading…
Cancel
Save