Browse Source

Merge branch 'develop/3.5' of github.com:thingsboard/thingsboard into feature/home-page

pull/8359/head
Igor Kulikov 4 years ago
parent
commit
f10113f20c
  1. 77
      application/src/main/data/json/edge/rule_chains/edge_root_rule_chain.json
  2. 23
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java
  3. 70
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java
  4. 28
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/relation/BaseRelationProcessor.java
  5. 66
      application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java
  6. 23
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  7. 23
      application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
  8. 2
      application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/NewPlatformVersionTriggerProcessor.java
  9. 16
      application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java
  10. 23
      application/src/test/java/org/thingsboard/server/edge/BaseAlarmEdgeTest.java
  11. 12
      common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java
  12. 8
      common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java
  13. 2
      dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java
  14. 2
      pom.xml
  15. 17
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/AbstractTbMsgPushNode.java
  16. 4
      ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts
  17. 8
      ui-ngx/src/assets/locale/locale.constant-en_US.json

77
application/src/main/data/json/tenant/edge_management/rule_chains/edge_root_rule_chain.json → application/src/main/data/json/edge/rule_chains/edge_root_rule_chain.json

@ -6,7 +6,8 @@
"firstRuleNodeId": null, "firstRuleNodeId": null,
"root": true, "root": true,
"debugMode": false, "debugMode": false,
"configuration": null "configuration": null,
"externalId": null
}, },
"metadata": { "metadata": {
"firstNodeIndex": 0, "firstNodeIndex": 0,
@ -23,7 +24,8 @@
"configuration": { "configuration": {
"persistAlarmRulesState": false, "persistAlarmRulesState": false,
"fetchAlarmRulesStateOnStart": false "fetchAlarmRulesStateOnStart": false
} },
"externalId": null
}, },
{ {
"additionalInfo": { "additionalInfo": {
@ -35,7 +37,8 @@
"debugMode": false, "debugMode": false,
"configuration": { "configuration": {
"defaultTTL": 0 "defaultTTL": 0
} },
"externalId": null
}, },
{ {
"additionalInfo": { "additionalInfo": {
@ -46,8 +49,10 @@
"name": "Save Client Attributes", "name": "Save Client Attributes",
"debugMode": false, "debugMode": false,
"configuration": { "configuration": {
"scope": "CLIENT_SCOPE" "scope": "CLIENT_SCOPE",
} "notifyDevice": "false"
},
"externalId": null
}, },
{ {
"additionalInfo": { "additionalInfo": {
@ -59,7 +64,8 @@
"debugMode": false, "debugMode": false,
"configuration": { "configuration": {
"version": 0 "version": 0
} },
"externalId": null
}, },
{ {
"additionalInfo": { "additionalInfo": {
@ -73,7 +79,8 @@
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
} },
"externalId": null
}, },
{ {
"additionalInfo": { "additionalInfo": {
@ -87,7 +94,8 @@
"scriptLang": "TBEL", "scriptLang": "TBEL",
"jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);", "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);",
"tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" "tbelScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
} },
"externalId": null
}, },
{ {
"additionalInfo": { "additionalInfo": {
@ -99,19 +107,34 @@
"debugMode": false, "debugMode": false,
"configuration": { "configuration": {
"timeoutInSeconds": 60 "timeoutInSeconds": 60
} },
"externalId": null
}, },
{ {
"additionalInfo": { "additionalInfo": {
"layoutX": 1129, "layoutX": 1126,
"layoutY": 52 "layoutY": 104
}, },
"type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode", "type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode",
"name": "Push to cloud", "name": "Push to cloud",
"debugMode": false, "debugMode": false,
"configuration": { "configuration": {
"scope": "SERVER_SCOPE" "scope": "SERVER_SCOPE"
} },
"externalId": null
},
{
"additionalInfo": {
"layoutX": 826,
"layoutY": 601
},
"type": "org.thingsboard.rule.engine.edge.TbMsgPushToCloudNode",
"name": "Push to cloud",
"debugMode": false,
"configuration": {
"scope": "SERVER_SCOPE"
},
"externalId": null
} }
], ],
"connections": [ "connections": [
@ -132,24 +155,14 @@
}, },
{ {
"fromIndex": 3, "fromIndex": 3,
"toIndex": 6, "toIndex": 1,
"type": "RPC Request to Device" "type": "Post telemetry"
},
{
"fromIndex": 3,
"toIndex": 5,
"type": "Other"
}, },
{ {
"fromIndex": 3, "fromIndex": 3,
"toIndex": 2, "toIndex": 2,
"type": "Post attributes" "type": "Post attributes"
}, },
{
"fromIndex": 3,
"toIndex": 1,
"type": "Post telemetry"
},
{ {
"fromIndex": 3, "fromIndex": 3,
"toIndex": 4, "toIndex": 4,
@ -157,23 +170,23 @@
}, },
{ {
"fromIndex": 3, "fromIndex": 3,
"toIndex": 7, "toIndex": 5,
"type": "Attributes Updated" "type": "Other"
}, },
{ {
"fromIndex": 3, "fromIndex": 3,
"toIndex": 7, "toIndex": 6,
"type": "Attributes Deleted" "type": "RPC Request to Device"
}, },
{ {
"fromIndex": 3, "fromIndex": 3,
"toIndex": 7, "toIndex": 8,
"type": "Timeseries Deleted" "type": "Attributes Deleted"
}, },
{ {
"fromIndex": 3, "fromIndex": 3,
"toIndex": 7, "toIndex": 8,
"type": "Timeseries Updated" "type": "Attributes Updated"
} }
], ],
"ruleChainConnections": null "ruleChainConnections": null

23
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/BaseEdgeProcessor.java

@ -485,4 +485,27 @@ public abstract class BaseEdgeProcessor {
} }
return customerId; return customerId;
} }
protected boolean isEntityExists(TenantId tenantId, EntityId entityId) {
switch (entityId.getEntityType()) {
case TENANT:
return tenantService.findTenantById(tenantId) != null;
case DEVICE:
return deviceService.findDeviceById(tenantId, new DeviceId(entityId.getId())) != null;
case ASSET:
return assetService.findAssetById(tenantId, new AssetId(entityId.getId())) != null;
case ENTITY_VIEW:
return entityViewService.findEntityViewById(tenantId, new EntityViewId(entityId.getId())) != null;
case CUSTOMER:
return customerService.findCustomerById(tenantId, new CustomerId(entityId.getId())) != null;
case USER:
return userService.findUserById(tenantId, new UserId(entityId.getId())) != null;
case DASHBOARD:
return dashboardService.findDashboardById(tenantId, new DashboardId(entityId.getId())) != null;
case EDGE:
return edgeService.findEdgeById(tenantId, new EdgeId(entityId.getId())) != null;
default:
return false;
}
}
} }

70
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/alarm/BaseAlarmProcessor.java

@ -19,19 +19,19 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.alarm.AlarmUpdateRequest;
import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.id.AlarmId; import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
import org.thingsboard.server.gen.edge.v1.UpdateMsgType; import org.thingsboard.server.gen.edge.v1.UpdateMsgType;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor; import org.thingsboard.server.service.edge.rpc.processor.BaseEdgeProcessor;
import java.util.UUID; import java.util.UUID;
@ -43,51 +43,59 @@ public abstract class BaseAlarmProcessor extends BaseEdgeProcessor {
log.trace("[{}] processAlarmMsg [{}]", tenantId, alarmUpdateMsg); log.trace("[{}] processAlarmMsg [{}]", tenantId, alarmUpdateMsg);
EntityId originatorId = getAlarmOriginator(tenantId, alarmUpdateMsg.getOriginatorName(), EntityId originatorId = getAlarmOriginator(tenantId, alarmUpdateMsg.getOriginatorName(),
EntityType.valueOf(alarmUpdateMsg.getOriginatorType())); EntityType.valueOf(alarmUpdateMsg.getOriginatorType()));
AlarmId alarmId = new AlarmId(new UUID(alarmUpdateMsg.getIdMSB(), alarmUpdateMsg.getIdLSB()));
if (originatorId == null) { if (originatorId == null) {
log.warn("Originator not found for the alarm msg {}", alarmUpdateMsg); log.warn("Originator not found for the alarm msg {}", alarmUpdateMsg);
return Futures.immediateFuture(null); return Futures.immediateFuture(null);
} }
try { try {
Alarm existentAlarm = alarmService.findLatestActiveByOriginatorAndType(tenantId, originatorId, alarmUpdateMsg.getType());
switch (alarmUpdateMsg.getMsgType()) { switch (alarmUpdateMsg.getMsgType()) {
case ENTITY_CREATED_RPC_MESSAGE: case ENTITY_CREATED_RPC_MESSAGE:
case ENTITY_UPDATED_RPC_MESSAGE: case ENTITY_UPDATED_RPC_MESSAGE:
if (existentAlarm == null || existentAlarm.getStatus().isCleared()) { Alarm alarm = new Alarm();
existentAlarm = new Alarm(); alarm.setId(alarmId);
existentAlarm.setTenantId(tenantId); alarm.setTenantId(tenantId);
existentAlarm.setType(alarmUpdateMsg.getName()); alarm.setType(alarmUpdateMsg.getName());
existentAlarm.setOriginator(originatorId); alarm.setOriginator(originatorId);
existentAlarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity())); alarm.setSeverity(AlarmSeverity.valueOf(alarmUpdateMsg.getSeverity()));
existentAlarm.setStartTs(alarmUpdateMsg.getStartTs()); alarm.setStartTs(alarmUpdateMsg.getStartTs());
existentAlarm.setClearTs(alarmUpdateMsg.getClearTs());
existentAlarm.setPropagate(alarmUpdateMsg.getPropagate());
}
var alarmStatus = AlarmStatus.valueOf(alarmUpdateMsg.getStatus()); var alarmStatus = AlarmStatus.valueOf(alarmUpdateMsg.getStatus());
existentAlarm.setCleared(alarmStatus.isCleared()); alarm.setClearTs(alarmUpdateMsg.getClearTs());
existentAlarm.setAcknowledged(alarmStatus.isAck()); alarm.setPropagate(alarmUpdateMsg.getPropagate());
existentAlarm.setAckTs(alarmUpdateMsg.getAckTs()); alarm.setCleared(alarmStatus.isCleared());
existentAlarm.setEndTs(alarmUpdateMsg.getEndTs()); alarm.setAcknowledged(alarmStatus.isAck());
existentAlarm.setDetails(JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails())); alarm.setAckTs(alarmUpdateMsg.getAckTs());
alarmService.createOrUpdateAlarm(existentAlarm); alarm.setEndTs(alarmUpdateMsg.getEndTs());
break; alarm.setDetails(JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails()));
if (UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE.equals(alarmUpdateMsg.getMsgType())) {
alarmService.createAlarm(AlarmCreateOrUpdateActiveRequest.fromAlarm(alarm, null, alarmId));
} else {
alarmService.updateAlarm(AlarmUpdateRequest.fromAlarm(alarm));
}
return Futures.immediateFuture(null);
case ALARM_ACK_RPC_MESSAGE: case ALARM_ACK_RPC_MESSAGE:
if (existentAlarm != null) { Alarm alarmToAck = alarmService.findAlarmById(tenantId, alarmId);
alarmService.acknowledgeAlarm(tenantId, existentAlarm.getId(), alarmUpdateMsg.getAckTs()); if (alarmToAck != null) {
alarmService.acknowledgeAlarm(tenantId, alarmId, alarmUpdateMsg.getAckTs());
} }
break; return Futures.immediateFuture(null);
case ALARM_CLEAR_RPC_MESSAGE: case ALARM_CLEAR_RPC_MESSAGE:
if (existentAlarm != null) { Alarm alarmToClear = alarmService.findAlarmById(tenantId, alarmId);
alarmService.clearAlarm(tenantId, existentAlarm.getId(), if (alarmToClear != null) {
alarmUpdateMsg.getAckTs(), JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails())); alarmService.clearAlarm(tenantId, alarmId, alarmUpdateMsg.getClearTs(),
JacksonUtil.OBJECT_MAPPER.readTree(alarmUpdateMsg.getDetails()));
} }
break; return Futures.immediateFuture(null);
case ENTITY_DELETED_RPC_MESSAGE: case ENTITY_DELETED_RPC_MESSAGE:
if (existentAlarm != null) { Alarm alarmToDelete = alarmService.findAlarmById(tenantId, alarmId);
alarmService.delAlarm(tenantId, existentAlarm.getId()); if (alarmToDelete != null) {
alarmService.delAlarm(tenantId, alarmId);
} }
break; return Futures.immediateFuture(null);
case UNRECOGNIZED:
default:
return handleUnsupportedMsgType(alarmUpdateMsg.getMsgType());
} }
return Futures.immediateFuture(null);
} catch (Exception e) { } catch (Exception e) {
log.error("[{}] Failed to process alarm update msg [{}]", tenantId, alarmUpdateMsg, e); log.error("[{}] Failed to process alarm update msg [{}]", tenantId, alarmUpdateMsg, e);
return Futures.immediateFailedFuture(e); return Futures.immediateFailedFuture(e);

28
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/relation/BaseRelationProcessor.java

@ -20,16 +20,9 @@ import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DashboardId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory; import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.EntityViewId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg; import org.thingsboard.server.gen.edge.v1.RelationUpdateMsg;
@ -80,25 +73,4 @@ public abstract class BaseRelationProcessor extends BaseEdgeProcessor {
return Futures.immediateFailedFuture(e); return Futures.immediateFailedFuture(e);
} }
} }
private boolean isEntityExists(TenantId tenantId, EntityId entityId) {
switch (entityId.getEntityType()) {
case DEVICE:
return deviceService.findDeviceById(tenantId, new DeviceId(entityId.getId())) != null;
case ASSET:
return assetService.findAssetById(tenantId, new AssetId(entityId.getId())) != null;
case ENTITY_VIEW:
return entityViewService.findEntityViewById(tenantId, new EntityViewId(entityId.getId())) != null;
case CUSTOMER:
return customerService.findCustomerById(tenantId, new CustomerId(entityId.getId())) != null;
case USER:
return userService.findUserById(tenantId, new UserId(entityId.getId())) != null;
case DASHBOARD:
return dashboardService.findDashboardById(tenantId, new DashboardId(entityId.getId())) != null;
case EDGE:
return edgeService.findEdgeById(tenantId, new EdgeId(entityId.getId())) != null;
default:
return false;
}
}
} }

66
application/src/main/java/org/thingsboard/server/service/edge/rpc/processor/telemetry/BaseTelemetryProcessor.java

@ -90,42 +90,46 @@ public abstract class BaseTelemetryProcessor extends BaseEdgeProcessor {
log.trace("[{}] processTelemetryMsg [{}]", tenantId, entityData); log.trace("[{}] processTelemetryMsg [{}]", tenantId, entityData);
List<ListenableFuture<Void>> result = new ArrayList<>(); List<ListenableFuture<Void>> result = new ArrayList<>();
EntityId entityId = constructEntityId(entityData.getEntityType(), entityData.getEntityIdMSB(), entityData.getEntityIdLSB()); EntityId entityId = constructEntityId(entityData.getEntityType(), entityData.getEntityIdMSB(), entityData.getEntityIdLSB());
if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg() || entityData.hasAttributesUpdatedMsg()) && entityId != null) { if (entityId != null && isEntityExists(tenantId, entityId)) {
Pair<TbMsgMetaData, CustomerId> pair = getBaseMsgMetadataAndCustomerId(tenantId, entityId); if ((entityData.hasPostAttributesMsg() || entityData.hasPostTelemetryMsg() || entityData.hasAttributesUpdatedMsg())) {
TbMsgMetaData metaData = pair.getKey(); Pair<TbMsgMetaData, CustomerId> pair = getBaseMsgMetadataAndCustomerId(tenantId, entityId);
CustomerId customerId = pair.getValue(); TbMsgMetaData metaData = pair.getKey();
metaData.putValue(DataConstants.MSG_SOURCE_KEY, getMsgSourceKey()); CustomerId customerId = pair.getValue();
if (entityData.hasPostAttributesMsg()) { metaData.putValue(DataConstants.MSG_SOURCE_KEY, getMsgSourceKey());
result.add(processPostAttributes(tenantId, customerId, entityId, entityData.getPostAttributesMsg(), metaData)); if (entityData.hasPostAttributesMsg()) {
} result.add(processPostAttributes(tenantId, customerId, entityId, entityData.getPostAttributesMsg(), metaData));
if (entityData.hasAttributesUpdatedMsg()) { }
metaData.putValue("scope", entityData.getPostAttributeScope()); if (entityData.hasAttributesUpdatedMsg()) {
result.add(processAttributesUpdate(tenantId, customerId, entityId, entityData.getAttributesUpdatedMsg(), metaData)); metaData.putValue("scope", entityData.getPostAttributeScope());
} result.add(processAttributesUpdate(tenantId, customerId, entityId, entityData.getAttributesUpdatedMsg(), metaData));
if (entityData.hasPostTelemetryMsg()) { }
result.add(processPostTelemetry(tenantId, customerId, entityId, entityData.getPostTelemetryMsg(), metaData)); if (entityData.hasPostTelemetryMsg()) {
} result.add(processPostTelemetry(tenantId, customerId, entityId, entityData.getPostTelemetryMsg(), metaData));
if (EntityType.DEVICE.equals(entityId.getEntityType())) { }
DeviceId deviceId = new DeviceId(entityId.getId()); if (EntityType.DEVICE.equals(entityId.getEntityType())) {
DeviceId deviceId = new DeviceId(entityId.getId());
long currentTs = System.currentTimeMillis(); long currentTs = System.currentTimeMillis();
TransportProtos.DeviceActivityProto deviceActivityMsg = TransportProtos.DeviceActivityProto.newBuilder() TransportProtos.DeviceActivityProto deviceActivityMsg = TransportProtos.DeviceActivityProto.newBuilder()
.setTenantIdMSB(tenantId.getId().getMostSignificantBits()) .setTenantIdMSB(tenantId.getId().getMostSignificantBits())
.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()) .setTenantIdLSB(tenantId.getId().getLeastSignificantBits())
.setDeviceIdMSB(deviceId.getId().getMostSignificantBits()) .setDeviceIdMSB(deviceId.getId().getMostSignificantBits())
.setDeviceIdLSB(deviceId.getId().getLeastSignificantBits()) .setDeviceIdLSB(deviceId.getId().getLeastSignificantBits())
.setLastActivityTime(currentTs).build(); .setLastActivityTime(currentTs).build();
log.trace("[{}][{}] device activity time is going to be updated, ts {}", tenantId, deviceId, currentTs); log.trace("[{}][{}] device activity time is going to be updated, ts {}", tenantId, deviceId, currentTs);
TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId); TopicPartitionInfo tpi = partitionService.resolve(ServiceType.TB_CORE, tenantId, deviceId);
tbCoreMsgProducer.send(tpi, new TbProtoQueueMsg<>(deviceId.getId(), tbCoreMsgProducer.send(tpi, new TbProtoQueueMsg<>(deviceId.getId(),
TransportProtos.ToCoreMsg.newBuilder().setDeviceActivityMsg(deviceActivityMsg).build()), null); TransportProtos.ToCoreMsg.newBuilder().setDeviceActivityMsg(deviceActivityMsg).build()), null);
}
} }
} if (entityData.hasAttributeDeleteMsg()) {
if (entityData.hasAttributeDeleteMsg()) { result.add(processAttributeDeleteMsg(tenantId, entityId, entityData.getAttributeDeleteMsg(), entityData.getEntityType()));
result.add(processAttributeDeleteMsg(tenantId, entityId, entityData.getAttributeDeleteMsg(), entityData.getEntityType())); }
} else {
log.warn("Skipping telemetry update msg because entity doesn't exists on edge, {}", entityData);
} }
return result; return result;
} }

23
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -22,7 +22,6 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -91,6 +90,7 @@ import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.notification.NotificationSettingsService; import org.thingsboard.server.dao.notification.NotificationSettingsService;
import org.thingsboard.server.dao.notification.NotificationTargetService;
import org.thingsboard.server.dao.queue.QueueService; import org.thingsboard.server.dao.queue.QueueService;
import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.settings.AdminSettingsService; import org.thingsboard.server.dao.settings.AdminSettingsService;
@ -177,6 +177,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
@Autowired @Autowired
private NotificationSettingsService notificationSettingsService; private NotificationSettingsService notificationSettingsService;
@Autowired
private NotificationTargetService notificationTargetService;
@Bean @Bean
protected BCryptPasswordEncoder passwordEncoder() { protected BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); return new BCryptPasswordEncoder();
@ -679,27 +682,15 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
@Override @Override
public void createDefaultNotificationConfigs() { public void createDefaultNotificationConfigs() {
try { log.info("Creating default notification configs for system admin");
log.info("Creating default notification configs for system admin"); if (notificationTargetService.findNotificationTargetsByTenantId(TenantId.SYS_TENANT_ID, new PageLink(1)).getTotalElements() == 0) {
notificationSettingsService.createDefaultNotificationConfigs(TenantId.SYS_TENANT_ID); notificationSettingsService.createDefaultNotificationConfigs(TenantId.SYS_TENANT_ID);
} catch (Exception e) {
if (StringUtils.contains(e.getMessage(), "already exists")) {
log.info("Default notification configs are already present for system admin, skipping");
} else {
throw e;
}
} }
PageDataIterable<TenantId> tenants = new PageDataIterable<>(tenantService::findTenantsIds, 500); PageDataIterable<TenantId> tenants = new PageDataIterable<>(tenantService::findTenantsIds, 500);
log.info("Creating default notification configs for all tenants"); log.info("Creating default notification configs for all tenants");
for (TenantId tenantId : tenants) { for (TenantId tenantId : tenants) {
try { if (notificationTargetService.findNotificationTargetsByTenantId(tenantId, new PageLink(1)).getTotalElements() == 0) {
notificationSettingsService.createDefaultNotificationConfigs(tenantId); notificationSettingsService.createDefaultNotificationConfigs(tenantId);
} catch (Exception e) {
if (StringUtils.contains(e.getMessage(), "already exists")) {
log.info("Default notification configs are already present for tenant {}, skipping", tenantId);
} else {
throw e;
}
} }
} }
} }

23
application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java

@ -65,6 +65,7 @@ public class InstallScripts {
public static final String JSON_DIR = "json"; public static final String JSON_DIR = "json";
public static final String SYSTEM_DIR = "system"; public static final String SYSTEM_DIR = "system";
public static final String TENANT_DIR = "tenant"; public static final String TENANT_DIR = "tenant";
public static final String EDGE_DIR = "edge";
public static final String DEVICE_PROFILE_DIR = "device_profile"; public static final String DEVICE_PROFILE_DIR = "device_profile";
public static final String DEMO_DIR = "demo"; public static final String DEMO_DIR = "demo";
public static final String RULE_CHAINS_DIR = "rule_chains"; public static final String RULE_CHAINS_DIR = "rule_chains";
@ -74,8 +75,6 @@ public class InstallScripts {
public static final String MODELS_LWM2M_DIR = "lwm2m-registry"; public static final String MODELS_LWM2M_DIR = "lwm2m-registry";
public static final String CREDENTIALS_DIR = "credentials"; public static final String CREDENTIALS_DIR = "credentials";
public static final String EDGE_MANAGEMENT = "edge_management";
public static final String JSON_EXT = ".json"; public static final String JSON_EXT = ".json";
public static final String XML_EXT = ".xml"; public static final String XML_EXT = ".xml";
@ -109,7 +108,7 @@ public class InstallScripts {
} }
private Path getEdgeRuleChainsDir() { private Path getEdgeRuleChainsDir() {
return Paths.get(getDataDir(), JSON_DIR, TENANT_DIR, EDGE_MANAGEMENT, RULE_CHAINS_DIR); return Paths.get(getDataDir(), JSON_DIR, EDGE_DIR, RULE_CHAINS_DIR);
} }
public String getDataDir() { public String getDataDir() {
@ -293,17 +292,15 @@ public class InstallScripts {
} }
private void doSaveLwm2mResource(TbResource resource) throws ThingsboardException { private void doSaveLwm2mResource(TbResource resource) throws ThingsboardException {
try { log.trace("Executing saveResource [{}]", resource);
log.trace("Executing saveResource [{}]", resource); if (StringUtils.isEmpty(resource.getData())) {
if (StringUtils.isEmpty(resource.getData())) { throw new DataValidationException("Resource data should be specified!");
throw new DataValidationException("Resource data should be specified!"); }
} toLwm2mResource(resource);
toLwm2mResource(resource); TbResource foundResource =
resourceService.getResource(TenantId.SYS_TENANT_ID, ResourceType.LWM2M_MODEL, resource.getResourceKey());
if (foundResource == null) {
resourceService.saveResource(resource); resourceService.saveResource(resource);
} catch (DataValidationException e) {
log.debug("[{}] {}", resource.getFileName(), e.getMessage());
} catch (Exception ex) {
throw ex;
} }
} }
} }

2
application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/NewPlatformVersionTriggerProcessor.java

@ -44,7 +44,7 @@ public class NewPlatformVersionTriggerProcessor implements NotificationRuleTrigg
@Override @Override
public NotificationInfo constructNotificationInfo(NewPlatformVersionTrigger trigger, NewPlatformVersionNotificationRuleTriggerConfig triggerConfig) { public NotificationInfo constructNotificationInfo(NewPlatformVersionTrigger trigger, NewPlatformVersionNotificationRuleTriggerConfig triggerConfig) {
return NewPlatformVersionNotificationInfo.builder() return NewPlatformVersionNotificationInfo.builder()
.message(trigger.getMessage().getMessage()) .message("New version available - " + trigger.getMessage().getLatestVersion())
.build(); .build();
} }

16
application/src/main/java/org/thingsboard/server/service/update/DefaultUpdateService.java

@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.info.BuildProperties;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.common.util.ThingsBoardThreadFactory;
@ -57,6 +58,9 @@ public class DefaultUpdateService implements UpdateService {
@Value("${updates.enabled}") @Value("${updates.enabled}")
private boolean updatesEnabled; private boolean updatesEnabled;
@Autowired(required = false)
private BuildProperties buildProperties;
@Autowired @Autowired
private NotificationRuleProcessingService notificationRuleProcessingService; private NotificationRuleProcessingService notificationRuleProcessingService;
@ -73,14 +77,11 @@ public class DefaultUpdateService implements UpdateService {
@PostConstruct @PostConstruct
private void init() { private void init() {
updateMessage = new UpdateMessage("", false, ""); version = buildProperties != null ? buildProperties.getVersion() : "unknown";
updateMessage = new UpdateMessage(false, version, "", "");
if (updatesEnabled) { if (updatesEnabled) {
try { try {
platform = System.getProperty("platform", "unknown"); platform = System.getProperty("platform", "unknown");
version = getClass().getPackage().getImplementationVersion();
if (version == null) {
version = "unknown";
}
instanceId = parseInstanceId(); instanceId = parseInstanceId();
checkUpdatesFuture = scheduler.scheduleAtFixedRate(checkUpdatesRunnable, 0, 1, TimeUnit.HOURS); checkUpdatesFuture = scheduler.scheduleAtFixedRate(checkUpdatesRunnable, 0, 1, TimeUnit.HOURS);
} catch (Exception e) { } catch (Exception e) {
@ -131,9 +132,10 @@ public class DefaultUpdateService implements UpdateService {
JsonNode response = restClient.postForObject(UPDATE_SERVER_BASE_URL + "/api/thingsboard/updates", request, JsonNode.class); JsonNode response = restClient.postForObject(UPDATE_SERVER_BASE_URL + "/api/thingsboard/updates", request, JsonNode.class);
UpdateMessage prevUpdateMessage = updateMessage; UpdateMessage prevUpdateMessage = updateMessage;
updateMessage = new UpdateMessage( updateMessage = new UpdateMessage(
response.get("message").asText(),
response.get("updateAvailable").asBoolean(), response.get("updateAvailable").asBoolean(),
version version,
"3.5.0",
"https://thingsboard.io/docs/user-guide/install/pe/upgrade-instructions"
); );
if (updateMessage.isUpdateAvailable() && !updateMessage.equals(prevUpdateMessage)) { if (updateMessage.isUpdateAvailable() && !updateMessage.equals(prevUpdateMessage)) {
notificationRuleProcessingService.process(TenantId.SYS_TENANT_ID, NewPlatformVersionTrigger.builder() notificationRuleProcessingService.process(TenantId.SYS_TENANT_ID, NewPlatformVersionTrigger.builder()

23
application/src/test/java/org/thingsboard/server/edge/BaseAlarmEdgeTest.java

@ -19,12 +19,14 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.google.protobuf.AbstractMessage; import com.google.protobuf.AbstractMessage;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.alarm.AlarmStatus; import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg; import org.thingsboard.server.gen.edge.v1.AlarmUpdateMsg;
@ -33,6 +35,7 @@ import org.thingsboard.server.gen.edge.v1.UplinkMsg;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@ -42,8 +45,11 @@ abstract public class BaseAlarmEdgeTest extends AbstractEdgeTest {
public void testSendAlarmToCloud() throws Exception { public void testSendAlarmToCloud() throws Exception {
Device device = saveDeviceOnCloudAndVerifyDeliveryToEdge(); Device device = saveDeviceOnCloudAndVerifyDeliveryToEdge();
UUID alarmUUID = UUID.randomUUID();
UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder(); UplinkMsg.Builder uplinkMsgBuilder = UplinkMsg.newBuilder();
AlarmUpdateMsg.Builder alarmUpdateMgBuilder = AlarmUpdateMsg.newBuilder(); AlarmUpdateMsg.Builder alarmUpdateMgBuilder = AlarmUpdateMsg.newBuilder();
alarmUpdateMgBuilder.setIdMSB(alarmUUID.getMostSignificantBits());
alarmUpdateMgBuilder.setIdLSB(alarmUUID.getLeastSignificantBits());
alarmUpdateMgBuilder.setName("alarm from edge"); alarmUpdateMgBuilder.setName("alarm from edge");
alarmUpdateMgBuilder.setStatus(AlarmStatus.ACTIVE_UNACK.name()); alarmUpdateMgBuilder.setStatus(AlarmStatus.ACTIVE_UNACK.name());
alarmUpdateMgBuilder.setSeverity(AlarmSeverity.CRITICAL.name()); alarmUpdateMgBuilder.setSeverity(AlarmSeverity.CRITICAL.name());
@ -65,6 +71,7 @@ abstract public class BaseAlarmEdgeTest extends AbstractEdgeTest {
Optional<AlarmInfo> foundAlarm = alarms.stream().filter(alarm -> alarm.getType().equals("alarm from edge")).findAny(); Optional<AlarmInfo> foundAlarm = alarms.stream().filter(alarm -> alarm.getType().equals("alarm from edge")).findAny();
Assert.assertTrue(foundAlarm.isPresent()); Assert.assertTrue(foundAlarm.isPresent());
AlarmInfo alarmInfo = foundAlarm.get(); AlarmInfo alarmInfo = foundAlarm.get();
Assert.assertEquals(new AlarmId(alarmUUID), alarmInfo.getId());
Assert.assertEquals(device.getId(), alarmInfo.getOriginator()); Assert.assertEquals(device.getId(), alarmInfo.getOriginator());
Assert.assertEquals(AlarmStatus.ACTIVE_UNACK, alarmInfo.getStatus()); Assert.assertEquals(AlarmStatus.ACTIVE_UNACK, alarmInfo.getStatus());
Assert.assertEquals(AlarmSeverity.CRITICAL, alarmInfo.getSeverity()); Assert.assertEquals(AlarmSeverity.CRITICAL, alarmInfo.getSeverity());
@ -85,12 +92,28 @@ abstract public class BaseAlarmEdgeTest extends AbstractEdgeTest {
Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg); Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg);
AlarmUpdateMsg alarmUpdateMsg = (AlarmUpdateMsg) latestMessage; AlarmUpdateMsg alarmUpdateMsg = (AlarmUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, alarmUpdateMsg.getMsgType()); Assert.assertEquals(UpdateMsgType.ENTITY_CREATED_RPC_MESSAGE, alarmUpdateMsg.getMsgType());
Assert.assertEquals(savedAlarm.getUuidId().getMostSignificantBits(), alarmUpdateMsg.getIdMSB());
Assert.assertEquals(savedAlarm.getUuidId().getLeastSignificantBits(), alarmUpdateMsg.getIdLSB());
Assert.assertEquals(savedAlarm.getType(), alarmUpdateMsg.getType()); Assert.assertEquals(savedAlarm.getType(), alarmUpdateMsg.getType());
Assert.assertEquals(savedAlarm.getName(), alarmUpdateMsg.getName()); Assert.assertEquals(savedAlarm.getName(), alarmUpdateMsg.getName());
Assert.assertEquals(device.getName(), alarmUpdateMsg.getOriginatorName()); Assert.assertEquals(device.getName(), alarmUpdateMsg.getOriginatorName());
Assert.assertEquals(savedAlarm.getStatus().name(), alarmUpdateMsg.getStatus()); Assert.assertEquals(savedAlarm.getStatus().name(), alarmUpdateMsg.getStatus());
Assert.assertEquals(savedAlarm.getSeverity().name(), alarmUpdateMsg.getSeverity()); Assert.assertEquals(savedAlarm.getSeverity().name(), alarmUpdateMsg.getSeverity());
// update alarm
String updatedDetails = "{\"testKey\":\"testValue\"}";
savedAlarm.setDetails(JacksonUtil.OBJECT_MAPPER.readTree(updatedDetails));
edgeImitator.expectMessageAmount(1);
savedAlarm = doPost("/api/alarm", savedAlarm, Alarm.class);
Assert.assertTrue(edgeImitator.waitForMessages());
latestMessage = edgeImitator.getLatestMessage();
Assert.assertTrue(latestMessage instanceof AlarmUpdateMsg);
alarmUpdateMsg = (AlarmUpdateMsg) latestMessage;
Assert.assertEquals(UpdateMsgType.ENTITY_UPDATED_RPC_MESSAGE, alarmUpdateMsg.getMsgType());
Assert.assertEquals(savedAlarm.getUuidId().getMostSignificantBits(), alarmUpdateMsg.getIdMSB());
Assert.assertEquals(savedAlarm.getUuidId().getLeastSignificantBits(), alarmUpdateMsg.getIdLSB());
Assert.assertEquals(updatedDetails, alarmUpdateMsg.getDetails());
// ack alarm // ack alarm
edgeImitator.expectMessageAmount(1); edgeImitator.expectMessageAmount(1);
doPost("/api/alarm/" + savedAlarm.getUuidId() + "/ack"); doPost("/api/alarm/" + savedAlarm.getUuidId() + "/ack");

12
common/data/src/main/java/org/thingsboard/server/common/data/UpdateMessage.java

@ -23,10 +23,14 @@ import lombok.Data;
@Data @Data
public class UpdateMessage { public class UpdateMessage {
@ApiModelProperty(position = 1, value = "The message about new platform update available.") @ApiModelProperty(position = 1, value = "'True' if new platform update is available.")
private final String message;
@ApiModelProperty(position = 2, value = "'True' if new platform update is available.")
private final boolean isUpdateAvailable; private final boolean isUpdateAvailable;
@ApiModelProperty(position = 3, value = "Current ThingsBoard version.") @ApiModelProperty(position = 2, value = "Current ThingsBoard version.")
private final String currentVersion; private final String currentVersion;
@ApiModelProperty(position = 3, value = "Latest ThingsBoard version.")
private final String latestVersion;
@ApiModelProperty(position = 4, value = "Upgrade instructions URL.")
private final String upgradeInstructionsUrl;
} }

8
common/data/src/main/java/org/thingsboard/server/common/data/alarm/AlarmCreateOrUpdateActiveRequest.java

@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import org.thingsboard.server.common.data.id.AlarmId;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
@ -61,11 +62,17 @@ public class AlarmCreateOrUpdateActiveRequest implements AlarmModificationReques
private UserId userId; private UserId userId;
private AlarmId edgeAlarmId;
public static AlarmCreateOrUpdateActiveRequest fromAlarm(Alarm a) { public static AlarmCreateOrUpdateActiveRequest fromAlarm(Alarm a) {
return fromAlarm(a, null); return fromAlarm(a, null);
} }
public static AlarmCreateOrUpdateActiveRequest fromAlarm(Alarm a, UserId userId) { public static AlarmCreateOrUpdateActiveRequest fromAlarm(Alarm a, UserId userId) {
return fromAlarm(a, userId, null);
}
public static AlarmCreateOrUpdateActiveRequest fromAlarm(Alarm a, UserId userId, AlarmId edgeAlarmId) {
return AlarmCreateOrUpdateActiveRequest.builder() return AlarmCreateOrUpdateActiveRequest.builder()
.tenantId(a.getTenantId()) .tenantId(a.getTenantId())
.customerId(a.getCustomerId()) .customerId(a.getCustomerId())
@ -81,6 +88,7 @@ public class AlarmCreateOrUpdateActiveRequest implements AlarmModificationReques
.propagateToTenant(a.isPropagateToTenant()) .propagateToTenant(a.isPropagateToTenant())
.propagateRelationTypes(a.getPropagateRelationTypes()).build()) .propagateRelationTypes(a.getPropagateRelationTypes()).build())
.userId(userId) .userId(userId)
.edgeAlarmId(edgeAlarmId)
.build(); .build();
} }

2
dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java

@ -245,7 +245,7 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
return toAlarmApiResult(alarmRepository.createOrUpdateActiveAlarm( return toAlarmApiResult(alarmRepository.createOrUpdateActiveAlarm(
request.getTenantId().getId(), request.getTenantId().getId(),
request.getCustomerId() != null ? request.getCustomerId().getId() : CustomerId.NULL_UUID, request.getCustomerId() != null ? request.getCustomerId().getId() : CustomerId.NULL_UUID,
UUID.randomUUID(), request.getEdgeAlarmId() != null ? request.getEdgeAlarmId().getId() : UUID.randomUUID(),
System.currentTimeMillis(), System.currentTimeMillis(),
request.getOriginator().getId(), request.getOriginator().getId(),
request.getOriginator().getEntityType().ordinal(), request.getOriginator().getEntityType().ordinal(),

2
pom.xml

@ -78,7 +78,7 @@
<zookeeper.version>3.5.5</zookeeper.version> <zookeeper.version>3.5.5</zookeeper.version>
<protobuf.version>3.21.9</protobuf.version> <protobuf.version>3.21.9</protobuf.version>
<grpc.version>1.42.1</grpc.version> <grpc.version>1.42.1</grpc.version>
<tbel.version>1.0.5</tbel.version> <tbel.version>1.0.6</tbel.version>
<lombok.version>1.18.18</lombok.version> <lombok.version>1.18.18</lombok.version>
<paho.client.version>1.2.4</paho.client.version> <paho.client.version>1.2.4</paho.client.version>
<paho.mqttv5.client.version>1.2.5</paho.mqttv5.client.version> <paho.mqttv5.client.version>1.2.5</paho.mqttv5.client.version>

17
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/edge/AbstractTbMsgPushNode.java

@ -74,7 +74,8 @@ public abstract class AbstractTbMsgPushNode<T extends BaseTbMsgPushNodeConfigura
protected S buildEvent(TbMsg msg, TbContext ctx) { protected S buildEvent(TbMsg msg, TbContext ctx) {
String msgType = msg.getType(); String msgType = msg.getType();
if (DataConstants.ALARM.equals(msgType)) { if (DataConstants.ALARM.equals(msgType)) {
return buildEvent(ctx.getTenantId(), EdgeEventActionType.ADDED, getUUIDFromMsgData(msg), getAlarmEventType(), null); EdgeEventActionType actionType = getAlarmActionType(msg);
return buildEvent(ctx.getTenantId(), actionType, getUUIDFromMsgData(msg), getAlarmEventType(), null);
} else { } else {
EdgeEventActionType actionType = getEdgeEventActionTypeByMsgType(msgType); EdgeEventActionType actionType = getEdgeEventActionTypeByMsgType(msgType);
Map<String, Object> entityBody = new HashMap<>(); Map<String, Object> entityBody = new HashMap<>();
@ -107,6 +108,20 @@ public abstract class AbstractTbMsgPushNode<T extends BaseTbMsgPushNodeConfigura
} }
} }
private static EdgeEventActionType getAlarmActionType(TbMsg msg) {
boolean isNewAlarm = Boolean.parseBoolean(msg.getMetaData().getValue(DataConstants.IS_NEW_ALARM));
boolean isClearedAlarm = Boolean.parseBoolean(msg.getMetaData().getValue(DataConstants.IS_CLEARED_ALARM));
EdgeEventActionType eventAction;
if (isNewAlarm) {
eventAction = EdgeEventActionType.ADDED;
} else if (isClearedAlarm) {
eventAction = EdgeEventActionType.ALARM_CLEAR;
} else {
eventAction = EdgeEventActionType.UPDATED;
}
return eventAction;
}
abstract S buildEvent(TenantId tenantId, EdgeEventActionType eventAction, UUID entityId, U eventType, JsonNode entityBody); abstract S buildEvent(TenantId tenantId, EdgeEventActionType eventAction, UUID entityId, U eventType, JsonNode entityBody);
abstract U getEventTypeByEntityType(EntityType entityType); abstract U getEventTypeByEntityType(EntityType entityType);

4
ui-ngx/src/app/modules/home/pages/rulechain/rulechains-table-config.resolver.ts

@ -142,11 +142,11 @@ export class RuleChainsTableConfigResolver implements Resolve<EntityTableConfig<
); );
} else if (ruleChainScope === 'edges') { } else if (ruleChainScope === 'edges') {
columns.push( columns.push(
new EntityTableColumn<RuleChain>('root', 'rulechain.edge-template-root', '60px', new EntityTableColumn<RuleChain>('root', 'rulechain.edge-template-root', '70px',
entity => { entity => {
return checkBoxCell(entity.root); return checkBoxCell(entity.root);
}), }),
new EntityTableColumn<RuleChain>('assignToEdge', 'rulechain.assign-to-edge', '60px', new EntityTableColumn<RuleChain>('assignToEdge', 'rulechain.assign-to-edge', '70px',
entity => { entity => {
return checkBoxCell(this.isAutoAssignToEdgeRuleChain(entity)); return checkBoxCell(this.isAutoAssignToEdgeRuleChain(entity));
}) })

8
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1396,10 +1396,10 @@
"create-new-device-profile": "Create a new one!", "create-new-device-profile": "Create a new one!",
"mqtt-device-topic-filters": "MQTT device topic filters", "mqtt-device-topic-filters": "MQTT device topic filters",
"mqtt-device-topic-filters-unique": "MQTT device topic filters need to be unique.", "mqtt-device-topic-filters-unique": "MQTT device topic filters need to be unique.",
"mqtt-device-topic-filters-spark-plug": "MQTT device topic filters SparkPlug.", "mqtt-device-topic-filters-spark-plug": "MQTT Sparkplug B Edge of Network (EoN) node.",
"mqtt-device-topic-filters-spark-plug-hint": "Default - telemetry. Example: namespace/group_id/message_type/edge_node_id/[device_id].", "mqtt-device-topic-filters-spark-plug-hint": "Allow connections from EoN nodes with Sparkplug B payload and topic format.",
"mqtt-device-topic-filters-spark-plug-attribute-metric-names": "SparkPlug attributes metric names", "mqtt-device-topic-filters-spark-plug-attribute-metric-names": "SparkPlug metrics to store as attributes.",
"mqtt-device-topic-filters-spark-plug-attribute-metric-names-hint": "Names of SparkPlug metrics that will be stored as device attributes. All other metrics will be stored as device telemetry", "mqtt-device-topic-filters-spark-plug-attribute-metric-names-hint": "Names of SparkPlug metrics that will be stored as device attributes. All other metrics will be stored as device telemetry.",
"mqtt-device-payload-type": "MQTT device payload", "mqtt-device-payload-type": "MQTT device payload",
"mqtt-device-payload-type-json": "JSON", "mqtt-device-payload-type-json": "JSON",
"mqtt-device-payload-type-proto": "Protobuf", "mqtt-device-payload-type-proto": "Protobuf",

Loading…
Cancel
Save