Commit e0881cfc44a857518d6ea58a73c05a8959e1b854

Authored by Volodymyr Babak
1 parent 5e46f3e7

Added Rule Chain Metadata Update Msg. Added assigned edges text to rule chain

... ... @@ -41,7 +41,11 @@ import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
41 41 import org.thingsboard.server.common.data.kv.LongDataEntry;
42 42 import org.thingsboard.server.common.data.page.TimePageData;
43 43 import org.thingsboard.server.common.data.page.TimePageLink;
  44 +import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
44 45 import org.thingsboard.server.common.data.rule.RuleChain;
  46 +import org.thingsboard.server.common.data.rule.RuleChainConnectionInfo;
  47 +import org.thingsboard.server.common.data.rule.RuleChainMetaData;
  48 +import org.thingsboard.server.common.data.rule.RuleNode;
45 49 import org.thingsboard.server.dao.asset.AssetService;
46 50 import org.thingsboard.server.dao.attributes.AttributesService;
47 51 import org.thingsboard.server.dao.device.DeviceService;
... ... @@ -55,16 +59,20 @@ import org.thingsboard.server.gen.edge.DashboardUpdateMsg;
55 59 import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
56 60 import org.thingsboard.server.gen.edge.EdgeConfiguration;
57 61 import org.thingsboard.server.gen.edge.EntityViewUpdateMsg;
  62 +import org.thingsboard.server.gen.edge.NodeConnectionInfoProto;
58 63 import org.thingsboard.server.gen.edge.RequestMsg;
59 64 import org.thingsboard.server.gen.edge.RequestMsgType;
60 65 import org.thingsboard.server.gen.edge.ResponseMsg;
  66 +import org.thingsboard.server.gen.edge.RuleChainConnectionInfoProto;
  67 +import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg;
61 68 import org.thingsboard.server.gen.edge.RuleChainUpdateMsg;
  69 +import org.thingsboard.server.gen.edge.RuleNodeProto;
62 70 import org.thingsboard.server.gen.edge.UpdateMsgType;
63 71 import org.thingsboard.server.gen.edge.UplinkMsg;
64 72 import org.thingsboard.server.gen.edge.UplinkResponseMsg;
65 73 import org.thingsboard.server.service.edge.EdgeContextComponent;
66 74
67   -import java.util.Arrays;
  75 +import java.util.ArrayList;
68 76 import java.util.Collections;
69 77 import java.util.List;
70 78 import java.util.Optional;
... ... @@ -146,7 +154,7 @@ public final class EdgeGrpcSession implements Cloneable {
146 154
147 155 void processHandleMessages() throws ExecutionException, InterruptedException {
148 156 Long queueStartTs = getQueueStartTs().get();
149   - // TODO: this 100 value must be chagned properly
  157 + // TODO: this 100 value must be changed properly
150 158 TimePageLink pageLink = new TimePageLink(30, queueStartTs + 1000);
151 159 TimePageData<Event> pageData;
152 160 UUID ifOffset = null;
... ... @@ -179,6 +187,10 @@ public final class EdgeGrpcSession implements Cloneable {
179 187 RuleChain ruleChain = objectMapper.readValue(entry.getData(), RuleChain.class);
180 188 onRuleChainUpdated(msgType, ruleChain);
181 189 break;
  190 + case RULE_CHAIN_METADATA:
  191 + RuleChainMetaData ruleChainMetaData = objectMapper.readValue(entry.getData(), RuleChainMetaData.class);
  192 + onRuleChainMetadataUpdated(msgType, ruleChainMetaData);
  193 + break;
182 194 }
183 195 } catch (Exception e) {
184 196 log.error("Exception during processing records from queue", e);
... ... @@ -244,6 +256,15 @@ public final class EdgeGrpcSession implements Cloneable {
244 256 .build());
245 257 }
246 258
  259 + private void onRuleChainMetadataUpdated(UpdateMsgType msgType, RuleChainMetaData ruleChainMetaData) {
  260 + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = constructRuleChainMetadataUpdatedMsg(msgType, ruleChainMetaData);
  261 + if (ruleChainMetadataUpdateMsg != null) {
  262 + outputStream.onNext(ResponseMsg.newBuilder()
  263 + .setRuleChainMetadataUpdateMsg(ruleChainMetadataUpdateMsg)
  264 + .build());
  265 + }
  266 + }
  267 +
247 268 private void onDashboardUpdated(UpdateMsgType msgType, Dashboard dashboard) {
248 269 outputStream.onNext(ResponseMsg.newBuilder()
249 270 .setDashboardUpdateMsg(constructDashboardUpdatedMsg(msgType, dashboard))
... ... @@ -281,6 +302,83 @@ public final class EdgeGrpcSession implements Cloneable {
281 302 return builder.build();
282 303 }
283 304
  305 + private RuleChainMetadataUpdateMsg constructRuleChainMetadataUpdatedMsg(UpdateMsgType msgType, RuleChainMetaData ruleChainMetaData) {
  306 + try {
  307 + RuleChainMetadataUpdateMsg.Builder builder = RuleChainMetadataUpdateMsg.newBuilder()
  308 + .setRuleChainIdMSB(ruleChainMetaData.getRuleChainId().getId().getMostSignificantBits())
  309 + .setRuleChainIdLSB(ruleChainMetaData.getRuleChainId().getId().getLeastSignificantBits())
  310 + .addAllNodes(constructNodes(ruleChainMetaData.getNodes()))
  311 + .addAllConnections(constructConnections(ruleChainMetaData.getConnections()))
  312 + .addAllRuleChainConnections(constructRuleChainConnections(ruleChainMetaData.getRuleChainConnections()));
  313 + if (ruleChainMetaData.getFirstNodeIndex() != null) {
  314 + builder.setFirstNodeIndex(ruleChainMetaData.getFirstNodeIndex());
  315 + }
  316 + builder.setMsgType(msgType);
  317 + return builder.build();
  318 + } catch (JsonProcessingException ex) {
  319 + log.error("Can't construct RuleChainMetadataUpdateMsg", ex);
  320 + }
  321 + return null;
  322 + }
  323 +
  324 + private List<RuleChainConnectionInfoProto> constructRuleChainConnections(List<RuleChainConnectionInfo> ruleChainConnections) throws JsonProcessingException {
  325 + List<RuleChainConnectionInfoProto> result = new ArrayList<>();
  326 + if (ruleChainConnections != null && !ruleChainConnections.isEmpty()) {
  327 + for (RuleChainConnectionInfo ruleChainConnectionInfo : ruleChainConnections) {
  328 + result.add(constructRuleChainConnection(ruleChainConnectionInfo));
  329 + }
  330 + }
  331 + return result;
  332 + }
  333 +
  334 + private RuleChainConnectionInfoProto constructRuleChainConnection(RuleChainConnectionInfo ruleChainConnectionInfo) throws JsonProcessingException {
  335 + return RuleChainConnectionInfoProto.newBuilder()
  336 + .setFromIndex(ruleChainConnectionInfo.getFromIndex())
  337 + .setTargetRuleChainIdMSB(ruleChainConnectionInfo.getTargetRuleChainId().getId().getMostSignificantBits())
  338 + .setTargetRuleChainIdLSB(ruleChainConnectionInfo.getTargetRuleChainId().getId().getLeastSignificantBits())
  339 + .setType(ruleChainConnectionInfo.getType())
  340 + .setAdditionalInfo(objectMapper.writeValueAsString(ruleChainConnectionInfo.getAdditionalInfo()))
  341 + .build();
  342 + }
  343 +
  344 + private List<NodeConnectionInfoProto> constructConnections(List<NodeConnectionInfo> connections) {
  345 + List<NodeConnectionInfoProto> result = new ArrayList<>();
  346 + if (connections != null && !connections.isEmpty()) {
  347 + for (NodeConnectionInfo connection : connections) {
  348 + result.add(constructConnection(connection));
  349 + }
  350 + }
  351 + return result;
  352 + }
  353 +
  354 + private NodeConnectionInfoProto constructConnection(NodeConnectionInfo connection) {
  355 + return NodeConnectionInfoProto.newBuilder()
  356 + .setFromIndex(connection.getFromIndex())
  357 + .setToIndex(connection.getToIndex())
  358 + .setType(connection.getType())
  359 + .build();
  360 + }
  361 +
  362 + private List<RuleNodeProto> constructNodes(List<RuleNode> nodes) throws JsonProcessingException {
  363 + List<RuleNodeProto> result = new ArrayList<>();
  364 + if (nodes != null && !nodes.isEmpty()) {
  365 + for (RuleNode node : nodes) {
  366 + result.add(constructNode(node));
  367 + }
  368 + }
  369 + return result;
  370 + }
  371 +
  372 + private RuleNodeProto constructNode(RuleNode node) throws JsonProcessingException {
  373 + return RuleNodeProto.newBuilder()
  374 + .setType(node.getType())
  375 + .setName(node.getName())
  376 + .setDebugMode(node.isDebugMode())
  377 + .setConfiguration(objectMapper.writeValueAsString(node.getConfiguration()))
  378 + .setAdditionalInfo(objectMapper.writeValueAsString(node.getAdditionalInfo()))
  379 + .build();
  380 + }
  381 +
284 382 private DashboardUpdateMsg constructDashboardUpdatedMsg(UpdateMsgType msgType, Dashboard dashboard) {
285 383 DashboardUpdateMsg.Builder builder = DashboardUpdateMsg.newBuilder()
286 384 .setMsgType(msgType)
... ...
... ... @@ -15,16 +15,13 @@
15 15 */
16 16 package org.thingsboard.server.dao.edge;
17 17
18   -import com.fasterxml.jackson.databind.JsonNode;
19 18 import com.google.common.util.concurrent.ListenableFuture;
20 19 import org.thingsboard.server.common.data.EntitySubtype;
21 20 import org.thingsboard.server.common.data.Event;
22   -import org.thingsboard.server.common.data.Tenant;
23 21 import org.thingsboard.server.common.data.edge.Edge;
24 22 import org.thingsboard.server.common.data.edge.EdgeSearchQuery;
25 23 import org.thingsboard.server.common.data.id.CustomerId;
26 24 import org.thingsboard.server.common.data.id.EdgeId;
27   -import org.thingsboard.server.common.data.id.EntityId;
28 25 import org.thingsboard.server.common.data.id.TenantId;
29 26 import org.thingsboard.server.common.data.page.TextPageData;
30 27 import org.thingsboard.server.common.data.page.TextPageLink;
... ...
  1 +/**
  2 + * Copyright © 2016-2019 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.edge;
  17 +
  18 +public enum EdgeQueueEntityType {
  19 + DASHBOARD, ASSET, DEVICE, ENTITY_VIEW, ALARM, RULE_CHAIN, RULE_CHAIN_METADATA
  20 +}
... ...
... ... @@ -16,11 +16,10 @@
16 16 package org.thingsboard.server.common.data.edge;
17 17
18 18 import lombok.Data;
19   -import org.thingsboard.server.common.data.EntityType;
20 19
21 20 @Data
22 21 public class EdgeQueueEntry {
23 22 private String type;
24   - private EntityType entityType;
  23 + private EdgeQueueEntityType entityType;
25 24 private String data;
26 25 }
... ...
... ... @@ -37,6 +37,7 @@ import org.thingsboard.server.gen.edge.EntityViewUpdateMsg;
37 37 import org.thingsboard.server.gen.edge.RequestMsg;
38 38 import org.thingsboard.server.gen.edge.RequestMsgType;
39 39 import org.thingsboard.server.gen.edge.ResponseMsg;
  40 +import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg;
40 41 import org.thingsboard.server.gen.edge.RuleChainUpdateMsg;
41 42 import org.thingsboard.server.gen.edge.UplinkMsg;
42 43 import org.thingsboard.server.gen.edge.UplinkResponseMsg;
... ... @@ -75,6 +76,7 @@ public class EdgeGrpcClient implements EdgeRpcClient {
75 76 Consumer<AssetUpdateMsg> onAssetUpdate,
76 77 Consumer<EntityViewUpdateMsg> onEntityViewUpdate,
77 78 Consumer<RuleChainUpdateMsg> onRuleChainUpdate,
  79 + Consumer<RuleChainMetadataUpdateMsg> onRuleChainMetadataUpdate,
78 80 Consumer<DashboardUpdateMsg> onDashboardUpdate,
79 81 Consumer<DownlinkMsg> onDownlink,
80 82 Consumer<Exception> onError) {
... ... @@ -90,7 +92,7 @@ public class EdgeGrpcClient implements EdgeRpcClient {
90 92 channel = builder.build();
91 93 EdgeRpcServiceGrpc.EdgeRpcServiceStub stub = EdgeRpcServiceGrpc.newStub(channel);
92 94 log.info("[{}] Sending a connect request to the TB!", edgeKey);
93   - this.inputStream = stub.handleMsgs(initOutputStream(edgeKey, onUplinkResponse, onEdgeUpdate, onDeviceUpdate, onAssetUpdate, onEntityViewUpdate, onRuleChainUpdate, onDashboardUpdate, onDownlink, onError));
  95 + this.inputStream = stub.handleMsgs(initOutputStream(edgeKey, onUplinkResponse, onEdgeUpdate, onDeviceUpdate, onAssetUpdate, onEntityViewUpdate, onRuleChainUpdate, onRuleChainMetadataUpdate, onDashboardUpdate, onDownlink, onError));
94 96 this.inputStream.onNext(RequestMsg.newBuilder()
95 97 .setMsgType(RequestMsgType.CONNECT_RPC_MESSAGE)
96 98 .setConnectRequestMsg(ConnectRequestMsg.newBuilder().setEdgeRoutingKey(edgeKey).setEdgeSecret(edgeSecret).build())
... ... @@ -120,6 +122,7 @@ public class EdgeGrpcClient implements EdgeRpcClient {
120 122 Consumer<AssetUpdateMsg> onAssetUpdate,
121 123 Consumer<EntityViewUpdateMsg> onEntityViewUpdate,
122 124 Consumer<RuleChainUpdateMsg> onRuleChainUpdate,
  125 + Consumer<RuleChainMetadataUpdateMsg> onRuleChainMetadataUpdate,
123 126 Consumer<DashboardUpdateMsg> onDashboardUpdate,
124 127 Consumer<DownlinkMsg> onDownlink,
125 128 Consumer<Exception> onError) {
... ... @@ -150,6 +153,9 @@ public class EdgeGrpcClient implements EdgeRpcClient {
150 153 } else if (responseMsg.hasRuleChainUpdateMsg()) {
151 154 log.debug("[{}] Rule Chain udpate message received {}", edgeKey, responseMsg.getRuleChainUpdateMsg());
152 155 onRuleChainUpdate.accept(responseMsg.getRuleChainUpdateMsg());
  156 + } else if (responseMsg.hasRuleChainMetadataUpdateMsg()) {
  157 + log.debug("[{}] Rule Chain Metadata udpate message received {}", edgeKey, responseMsg.getRuleChainMetadataUpdateMsg());
  158 + onRuleChainMetadataUpdate.accept(responseMsg.getRuleChainMetadataUpdateMsg());
153 159 } else if (responseMsg.hasDashboardUpdateMsg()) {
154 160 log.debug("[{}] Dashboard message received {}", edgeKey, responseMsg.getDashboardUpdateMsg());
155 161 onDashboardUpdate.accept(responseMsg.getDashboardUpdateMsg());
... ...
... ... @@ -21,6 +21,7 @@ import org.thingsboard.server.gen.edge.DeviceUpdateMsg;
21 21 import org.thingsboard.server.gen.edge.DownlinkMsg;
22 22 import org.thingsboard.server.gen.edge.EdgeConfiguration;
23 23 import org.thingsboard.server.gen.edge.EntityViewUpdateMsg;
  24 +import org.thingsboard.server.gen.edge.RuleChainMetadataUpdateMsg;
24 25 import org.thingsboard.server.gen.edge.RuleChainUpdateMsg;
25 26 import org.thingsboard.server.gen.edge.UplinkMsg;
26 27 import org.thingsboard.server.gen.edge.UplinkResponseMsg;
... ... @@ -37,6 +38,7 @@ public interface EdgeRpcClient {
37 38 Consumer<AssetUpdateMsg> onAssetUpdate,
38 39 Consumer<EntityViewUpdateMsg> onEntityViewUpdate,
39 40 Consumer<RuleChainUpdateMsg> onRuleChainUpdate,
  41 + Consumer<RuleChainMetadataUpdateMsg> onRuleChainMetadataUpdate,
40 42 Consumer<DashboardUpdateMsg> onDashboardUpdate,
41 43 Consumer<DownlinkMsg> onDownlink,
42 44 Consumer<Exception> onError);
... ...
... ... @@ -43,10 +43,11 @@ message ResponseMsg {
43 43 UplinkResponseMsg uplinkResponseMsg = 2;
44 44 DeviceUpdateMsg deviceUpdateMsg = 3;
45 45 RuleChainUpdateMsg ruleChainUpdateMsg = 4;
46   - DashboardUpdateMsg dashboardUpdateMsg = 5;
47   - AssetUpdateMsg assetUpdateMsg = 6;
48   - EntityViewUpdateMsg entityViewUpdateMsg = 7;
49   - DownlinkMsg downlinkMsg = 8;
  46 + RuleChainMetadataUpdateMsg ruleChainMetadataUpdateMsg = 5;
  47 + DashboardUpdateMsg dashboardUpdateMsg = 6;
  48 + AssetUpdateMsg assetUpdateMsg = 7;
  49 + EntityViewUpdateMsg entityViewUpdateMsg = 8;
  50 + DownlinkMsg downlinkMsg = 9;
50 51 }
51 52
52 53 enum RequestMsgType {
... ... @@ -127,6 +128,38 @@ message RuleChainUpdateMsg {
127 128 string configuration = 9;
128 129 }
129 130
  131 +message RuleChainMetadataUpdateMsg {
  132 + UpdateMsgType msgType = 1;
  133 + int64 ruleChainIdMSB = 2;
  134 + int64 ruleChainIdLSB = 3;
  135 + int32 firstNodeIndex = 4;
  136 + repeated RuleNodeProto nodes = 5;
  137 + repeated NodeConnectionInfoProto connections = 6;
  138 + repeated RuleChainConnectionInfoProto ruleChainConnections = 7;
  139 +}
  140 +
  141 +message RuleNodeProto {
  142 + string type = 1;
  143 + string name = 2;
  144 + bool debugMode = 3;
  145 + string configuration = 4;
  146 + string additionalInfo = 5;
  147 +}
  148 +
  149 +message NodeConnectionInfoProto {
  150 + int32 fromIndex = 1;
  151 + int32 toIndex = 2;
  152 + string type = 3;
  153 +}
  154 +
  155 +message RuleChainConnectionInfoProto {
  156 + int32 fromIndex = 1;
  157 + int64 targetRuleChainIdMSB = 2;
  158 + int64 targetRuleChainIdLSB = 3;
  159 + string type = 4;
  160 + string additionalInfo = 5;
  161 +}
  162 +
130 163 message DashboardUpdateMsg {
131 164 UpdateMsgType msgType = 1;
132 165 int64 idMSB = 2;
... ...
... ... @@ -15,12 +15,10 @@
15 15 */
16 16 package org.thingsboard.server.dao.edge;
17 17
18   -import com.fasterxml.jackson.databind.JsonNode;
19 18 import com.fasterxml.jackson.databind.ObjectMapper;
20 19 import com.google.common.base.Function;
21 20 import com.google.common.util.concurrent.Futures;
22 21 import com.google.common.util.concurrent.ListenableFuture;
23   -import lombok.Data;
24 22 import lombok.extern.slf4j.Slf4j;
25 23 import org.springframework.beans.factory.annotation.Autowired;
26 24 import org.springframework.cache.Cache;
... ... @@ -31,12 +29,16 @@ import org.springframework.stereotype.Service;
31 29 import org.springframework.util.StringUtils;
32 30 import org.thingsboard.server.common.data.Customer;
33 31 import org.thingsboard.server.common.data.DataConstants;
  32 +import org.thingsboard.server.common.data.Device;
34 33 import org.thingsboard.server.common.data.EntitySubtype;
35 34 import org.thingsboard.server.common.data.EntityType;
  35 +import org.thingsboard.server.common.data.EntityView;
36 36 import org.thingsboard.server.common.data.Event;
37 37 import org.thingsboard.server.common.data.ShortEdgeInfo;
38 38 import org.thingsboard.server.common.data.Tenant;
  39 +import org.thingsboard.server.common.data.asset.Asset;
39 40 import org.thingsboard.server.common.data.edge.Edge;
  41 +import org.thingsboard.server.common.data.edge.EdgeQueueEntityType;
40 42 import org.thingsboard.server.common.data.edge.EdgeQueueEntry;
41 43 import org.thingsboard.server.common.data.edge.EdgeSearchQuery;
42 44 import org.thingsboard.server.common.data.id.CustomerId;
... ... @@ -50,6 +52,7 @@ import org.thingsboard.server.common.data.page.TimePageLink;
50 52 import org.thingsboard.server.common.data.relation.EntityRelation;
51 53 import org.thingsboard.server.common.data.relation.EntitySearchDirection;
52 54 import org.thingsboard.server.common.data.rule.RuleChain;
  55 +import org.thingsboard.server.common.data.rule.RuleChainMetaData;
53 56 import org.thingsboard.server.common.msg.TbMsg;
54 57 import org.thingsboard.server.dao.customer.CustomerDao;
55 58 import org.thingsboard.server.dao.dashboard.DashboardService;
... ... @@ -328,62 +331,118 @@ public class BaseEdgeService extends AbstractEntityService implements EdgeServic
328 331
329 332 }
330 333
331   - private void processDevice(TenantId tenantId, TbMsg tbMsg) {
332   - // TODO
333   - }
334   -
335   - private void processDashboard(TenantId tenantId, TbMsg tbMsg) {
336   - processAssignedEntity(tenantId, tbMsg, EntityType.DASHBOARD);
337   - }
338   -
339   - private void processEntityView(TenantId tenantId, TbMsg tbMsg) {
340   - // TODO
  334 + private void processDevice(TenantId tenantId, TbMsg tbMsg) throws IOException {
  335 + switch (tbMsg.getType()) {
  336 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  337 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  338 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DEVICE);
  339 + break;
  340 + case DataConstants.ENTITY_DELETED:
  341 + case DataConstants.ENTITY_CREATED:
  342 + case DataConstants.ENTITY_UPDATED:
  343 + Device device = mapper.readValue(tbMsg.getData(), Device.class);
  344 + if (device.getEdgeId() != null) {
  345 + pushEventsToEdge(tenantId, device.getEdgeId(), EdgeQueueEntityType.DEVICE, tbMsg);
  346 + }
  347 + break;
  348 + default:
  349 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  350 + }
341 351 }
342 352
343   - private void processAsset(TenantId tenantId, TbMsg tbMsg) {
344   - // TODO
  353 + private void processAsset(TenantId tenantId, TbMsg tbMsg) throws IOException {
  354 + switch (tbMsg.getType()) {
  355 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  356 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  357 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ASSET);
  358 + break;
  359 + case DataConstants.ENTITY_DELETED:
  360 + case DataConstants.ENTITY_CREATED:
  361 + case DataConstants.ENTITY_UPDATED:
  362 + Asset asset = mapper.readValue(tbMsg.getData(), Asset.class);
  363 + if (asset.getEdgeId() != null) {
  364 + pushEventsToEdge(tenantId, asset.getEdgeId(), EdgeQueueEntityType.ASSET, tbMsg);
  365 + }
  366 + break;
  367 + default:
  368 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  369 + }
345 370 }
346 371
347   - private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EntityType entityType) {
348   - EdgeId edgeId;
  372 + private void processEntityView(TenantId tenantId, TbMsg tbMsg) throws IOException {
349 373 switch (tbMsg.getType()) {
350 374 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
351   - edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("assignedEdgeId")));
352   - pushEventToEdge(tenantId, edgeId, tbMsg.getType(), entityType, tbMsg.getData());
353   - break;
354 375 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
355   - edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("unassignedEdgeId")));
356   - pushEventToEdge(tenantId, edgeId, tbMsg.getType(), entityType, tbMsg.getData());
  376 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.ENTITY_VIEW);
357 377 break;
  378 + case DataConstants.ENTITY_DELETED:
  379 + case DataConstants.ENTITY_CREATED:
  380 + case DataConstants.ENTITY_UPDATED:
  381 + EntityView entityView = mapper.readValue(tbMsg.getData(), EntityView.class);
  382 + if (entityView.getEdgeId() != null) {
  383 + pushEventsToEdge(tenantId, entityView.getEdgeId(), EdgeQueueEntityType.ENTITY_VIEW, tbMsg);
  384 + }
  385 + break;
  386 + default:
  387 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
358 388 }
359 389 }
360 390
  391 + private void processDashboard(TenantId tenantId, TbMsg tbMsg) throws IOException {
  392 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.DASHBOARD);
  393 + }
  394 +
361 395 private void processRuleChain(TenantId tenantId, TbMsg tbMsg) throws IOException {
362 396 switch (tbMsg.getType()) {
363 397 case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
364 398 case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
365   - processAssignedEntity(tenantId, tbMsg, EntityType.RULE_CHAIN);
  399 + processAssignedEntity(tenantId, tbMsg, EdgeQueueEntityType.RULE_CHAIN);
366 400 break;
367 401 case DataConstants.ENTITY_DELETED:
368 402 case DataConstants.ENTITY_CREATED:
369 403 case DataConstants.ENTITY_UPDATED:
370 404 RuleChain ruleChain = mapper.readValue(tbMsg.getData(), RuleChain.class);
371   - for (ShortEdgeInfo assignedEdge : ruleChain.getAssignedEdges()) {
372   - pushEventToEdge(tenantId, assignedEdge.getEdgeId(), tbMsg.getType(), EntityType.RULE_CHAIN, tbMsg.getData());
  405 + if (ruleChain.getAssignedEdges() != null && !ruleChain.getAssignedEdges().isEmpty()) {
  406 + for (ShortEdgeInfo assignedEdge : ruleChain.getAssignedEdges()) {
  407 + pushEventsToEdge(tenantId, assignedEdge.getEdgeId(), EdgeQueueEntityType.RULE_CHAIN, tbMsg);
  408 + }
373 409 }
374 410 break;
375 411 default:
376   - log.warn("Unsupported message type " + tbMsg.getType());
  412 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  413 + }
  414 + }
  415 +
  416 + private void processAssignedEntity(TenantId tenantId, TbMsg tbMsg, EdgeQueueEntityType entityType) throws IOException {
  417 + EdgeId edgeId;
  418 + switch (tbMsg.getType()) {
  419 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  420 + edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("assignedEdgeId")));
  421 + pushEventsToEdge(tenantId, edgeId, entityType, tbMsg);
  422 + break;
  423 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  424 + edgeId = new EdgeId(UUID.fromString(tbMsg.getMetaData().getValue("unassignedEdgeId")));
  425 + pushEventsToEdge(tenantId, edgeId, entityType, tbMsg);
  426 + break;
377 427 }
  428 + }
  429 +
  430 + private void pushEventsToEdge(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, TbMsg tbMsg) throws IOException {
  431 + log.debug("Pushing event(s) to edge queue. tenantId [{}], edgeId [{}], entityType [{}], tbMsg [{}]", tenantId, edgeId, entityType, tbMsg);
  432 +
  433 + pushEventsToEdge(tenantId, edgeId, entityType, tbMsg.getType(), tbMsg.getData());
378 434
  435 + if (entityType.equals(EdgeQueueEntityType.RULE_CHAIN)) {
  436 + pushRuleChainMetadataToEdge(tenantId, edgeId, tbMsg);
  437 + }
379 438 }
380 439
381   - private void pushEventToEdge(TenantId tenantId, EdgeId edgeId, String type, EntityType entityType, String data) {
382   - log.debug("Pushing event to edge queue. tenantId [{}], edgeId [{}], type [{}], data [{}]", tenantId, edgeId, type, data);
  440 + private void pushEventsToEdge(TenantId tenantId, EdgeId edgeId, EdgeQueueEntityType entityType, String type, String data) throws IOException {
  441 + log.debug("Pushing single event to edge queue. tenantId [{}], edgeId [{}], entityType [{}], type[{}], data [{}]", tenantId, edgeId, entityType, type, data);
383 442
384 443 EdgeQueueEntry queueEntry = new EdgeQueueEntry();
385   - queueEntry.setType(type);
386 444 queueEntry.setEntityType(entityType);
  445 + queueEntry.setType(type);
387 446 queueEntry.setData(data);
388 447
389 448 Event event = new Event();
... ... @@ -394,6 +453,20 @@ public class BaseEdgeService extends AbstractEntityService implements EdgeServic
394 453 eventService.saveAsync(event);
395 454 }
396 455
  456 + private void pushRuleChainMetadataToEdge(TenantId tenantId, EdgeId edgeId, TbMsg tbMsg) throws IOException {
  457 + RuleChain ruleChain = mapper.readValue(tbMsg.getData(), RuleChain.class);
  458 + switch (tbMsg.getType()) {
  459 + case DataConstants.ENTITY_ASSIGNED_TO_EDGE:
  460 + case DataConstants.ENTITY_UNASSIGNED_FROM_EDGE:
  461 + case DataConstants.ENTITY_UPDATED:
  462 + RuleChainMetaData ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, ruleChain.getId());
  463 + pushEventsToEdge(tenantId, edgeId, EdgeQueueEntityType.RULE_CHAIN_METADATA, tbMsg.getType(), mapper.writeValueAsString(ruleChainMetaData));
  464 + break;
  465 + default:
  466 + log.warn("Unsupported msgType [{}], tbMsg [{}]", tbMsg.getType(), tbMsg);
  467 + }
  468 + }
  469 +
397 470 @Override
398 471 public TimePageData<Event> findQueueEvents(TenantId tenantId, EdgeId edgeId, TimePageLink pageLink) {
399 472 return eventService.findEvents(tenantId, edgeId, DataConstants.EDGE_QUEUE_EVENT_TYPE, pageLink);
... ...
... ... @@ -388,17 +388,24 @@ function RuleChainService($http, $q, $filter, $ocLazyLoad, $translate, types, co
388 388 }
389 389
390 390 function prepareRuleChain(ruleChain) {
  391 + ruleChain.assignedEdgesText = "";
391 392 ruleChain.assignedEdgesIds = [];
  393 +
392 394 if (ruleChain.assignedEdges && ruleChain.assignedEdges.length) {
  395 + var assignedEdgesTitles = [];
393 396 for (var j = 0; j < ruleChain.assignedEdges.length; j++) {
394 397 var assignedEdge = ruleChain.assignedEdges[j];
395 398 ruleChain.assignedEdgesIds.push(assignedEdge.edgeId.id);
  399 + assignedEdgesTitles.push(assignedEdge.title);
396 400 }
  401 + ruleChain.assignedEdgesText = assignedEdgesTitles.join(', ');
397 402 }
  403 +
398 404 return ruleChain;
399 405 }
400 406
401 407 function cleanRuleChain(ruleChain) {
  408 + delete ruleChain.assignedEdgesText;
402 409 delete ruleChain.assignedEdgesIds;
403 410 return ruleChain;
404 411 }
... ...
... ... @@ -251,6 +251,7 @@ export default function ImportExport($log, $translate, $q, $mdDialog, $document,
251 251 ruleChain.firstRuleNodeId = null;
252 252 }
253 253 ruleChain.root = false;
  254 + delete ruleChain.assignedEdgesText;
254 255 return ruleChain;
255 256 }
256 257
... ...
... ... @@ -1436,7 +1436,8 @@
1436 1436 "assign-to-edges": "Assign Rule Chain(s) To Edges",
1437 1437 "assign-to-edges-text": "Please select the edges to assign the rulechain(s)",
1438 1438 "unassign-from-edges": "Unassign Rule Chain(s) From Edges",
1439   - "unassign-from-edges-text": "Please select the edges to unassign from the rulechain(s)"
  1439 + "unassign-from-edges-text": "Please select the edges to unassign from the rulechain(s)",
  1440 + "assigned-to-edges": "Assigned to edges"
1440 1441 },
1441 1442 "rulenode": {
1442 1443 "details": "Details",
... ...
  1 +/**
  2 + * Copyright © 2016-2019 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +.tb-rule-chain-assigned-edges {
  17 + display: block;
  18 + display: -webkit-box; /* stylelint-disable-line value-no-vendor-prefix */
  19 + height: 34px;
  20 + margin-bottom: 4px;
  21 + overflow: hidden;
  22 + text-overflow: ellipsis;
  23 + -webkit-line-clamp: 2;
  24 + -webkit-box-orient: vertical; /* stylelint-disable-line property-no-vendor-prefix */
  25 +}
... ...
... ... @@ -15,4 +15,5 @@
15 15 limitations under the License.
16 16
17 17 -->
  18 +<div class="tb-small tb-rule-chain-assigned-edges" ng-show="vm.parentCtl.ruleChainsScope === 'tenant' && vm.item.assignedEdgesText">{{'rulechain.assigned-to-edges' | translate}}: '{{vm.item.assignedEdgesText}}'</div>
18 19 <div ng-if="item && item.root" translate>rulechain.root</div>
... ...
... ... @@ -36,6 +36,11 @@
36 36 </div>
37 37
38 38 <md-content class="md-padding tb-rulechain-fieldset" layout="column">
  39 + <md-input-container class="md-block"
  40 + ng-show="!isEdit && ruleChain.assignedEdgesText && ruleChainScope === 'tenant'">
  41 + <label translate>rulechain.assigned-to-edges</label>
  42 + <input ng-model="ruleChain.assignedEdgesText" disabled>
  43 + </md-input-container>
39 44 <fieldset ng-disabled="$root.loading || !isEdit || isReadOnly">
40 45 <md-input-container class="md-block">
41 46 <label translate>rulechain.name</label>
... ...
... ... @@ -37,11 +37,12 @@ export default function RuleChainDirective($compile, $templateCache, $mdDialog,
37 37 scope: {
38 38 ruleChain: '=',
39 39 isEdit: '=',
  40 + ruleChainScope: '=',
40 41 isReadOnly: '=',
41 42 theForm: '=',
42 43 onSetRootRuleChain: '&',
43 44 onExportRuleChain: '&',
44   - onDeleteRuleChain: '&'
  45 + onDeleteRuleChain: '&',
45 46 }
46 47 };
47 48 }
... ...
... ... @@ -22,6 +22,8 @@ import addRuleChainsToEdgeTemplate from "./add-rulechains-to-edge.tpl.html";
22 22
23 23 /* eslint-enable import/no-unresolved, import/default */
24 24
  25 +import './rulechain-card.scss';
  26 +
25 27 /*@ngInject*/
26 28 export default function RuleChainsController(ruleChainService, userService, importExport, $state,
27 29 $stateParams, $filter, $translate, $mdDialog, $document, $q, types) {
... ...
... ... @@ -24,6 +24,7 @@
24 24 <md-tab label="{{ 'rulechain.details' | translate }}">
25 25 <tb-rule-chain rule-chain="vm.grid.operatingItem()"
26 26 is-edit="vm.grid.detailsConfig.isDetailsEditMode"
  27 + rule-chain-scope="vm.ruleChainsScope"
27 28 is-read-only="vm.grid.isDetailsReadOnly(vm.grid.operatingItem())"
28 29 the-form="vm.grid.detailsForm"
29 30 on-set-root-rule-chain="vm.setRootRuleChain(event, vm.grid.detailsConfig.currentItem)"
... ...