Browse Source

alarm state improvements (added details to alarm from device profile details pattern)

pull/3678/head
YevhenBondarenko 6 years ago
committed by Andrew Shvayka
parent
commit
ecf530c63e
  1. 53
      rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java

53
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java

@ -16,6 +16,7 @@
package org.thingsboard.rule.engine.profile;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.rule.engine.action.TbAlarmResult;
@ -29,6 +30,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus;
import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.query.EntityKeyType;
import org.thingsboard.server.common.data.query.KeyFilter;
import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.common.msg.queue.ServiceQueue;
@ -74,7 +76,7 @@ class AlarmState {
public <T> boolean createOrClearAlarms(TbContext ctx, T data, SnapshotUpdate update, BiFunction<AlarmRuleState, T, AlarmEvalResult> evalFunction) {
boolean stateUpdate = false;
AlarmSeverity resultSeverity = null;
AlarmRuleState resultState = null;
log.debug("[{}] processing update: {}", alarmDefinition.getId(), data);
for (AlarmRuleState state : createRulesSortedBySeverityDesc) {
if (!validateUpdate(update, state)) {
@ -84,15 +86,15 @@ class AlarmState {
AlarmEvalResult evalResult = evalFunction.apply(state, data);
stateUpdate |= state.checkUpdate();
if (AlarmEvalResult.TRUE.equals(evalResult)) {
resultSeverity = state.getSeverity();
resultState = state;
break;
} else if (AlarmEvalResult.FALSE.equals(evalResult)) {
state.clear();
stateUpdate |= state.checkUpdate();
}
}
if (resultSeverity != null) {
TbAlarmResult result = calculateAlarmResult(ctx, resultSeverity);
if (resultState != null) {
TbAlarmResult result = calculateAlarmResult(ctx, resultState, data);
if (result != null) {
pushMsg(ctx, result);
}
@ -186,7 +188,8 @@ class AlarmState {
}
}
private TbAlarmResult calculateAlarmResult(TbContext ctx, AlarmSeverity severity) {
private <T> TbAlarmResult calculateAlarmResult(TbContext ctx, AlarmRuleState ruleState, T data) {
AlarmSeverity severity = ruleState.getSeverity();
if (currentAlarm != null) {
// TODO: In some extremely rare cases, we might miss the event of alarm clear (If one use in-mem queue and restarted the server) or (if one manipulated the rule chain).
// Maybe we should fetch alarm every time?
@ -212,7 +215,7 @@ class AlarmState {
currentAlarm.setSeverity(severity);
currentAlarm.setStartTs(System.currentTimeMillis());
currentAlarm.setEndTs(currentAlarm.getStartTs());
currentAlarm.setDetails(JacksonUtil.OBJECT_MAPPER.createObjectNode());
currentAlarm.setDetails(createDetails(ruleState, (DataSnapshot) data));
currentAlarm.setOriginator(originator);
currentAlarm.setTenantId(ctx.getTenantId());
currentAlarm.setPropagate(alarmDefinition.isPropagate());
@ -225,6 +228,44 @@ class AlarmState {
}
}
private <T> JsonNode createDetails(AlarmRuleState ruleState, DataSnapshot dataSnapshot) {
ObjectNode details = JacksonUtil.OBJECT_MAPPER.createObjectNode();
String alarmDetails = ruleState.getAlarmRule().getAlarmDetails();
if (alarmDetails != null) {
for (KeyFilter keyFilter : ruleState.getAlarmRule().getCondition().getCondition()) {
EntityKeyValue entityKeyValue = dataSnapshot.getValue(keyFilter.getKey());
alarmDetails = alarmDetails.replaceAll(String.format("\\$\\{%s}", keyFilter.getKey().getKey()), getValueAsString(entityKeyValue));
}
details.put("data", alarmDetails);
}
return details;
}
private static String getValueAsString(EntityKeyValue entityKeyValue) {
Object result = null;
switch (entityKeyValue.getDataType()) {
case STRING:
result = entityKeyValue.getStrValue();
break;
case JSON:
result = entityKeyValue.getJsonValue();
break;
case LONG:
result = String.valueOf(entityKeyValue.getLngValue());
break;
case DOUBLE:
result = String.valueOf(entityKeyValue.getDblValue());
break;
case BOOLEAN:
result = String.valueOf(entityKeyValue.getBoolValue());
break;
}
return String.valueOf(result);
}
public boolean processAlarmClear(TbContext ctx, Alarm alarmNf) {
boolean updated = false;
if (currentAlarm != null && currentAlarm.getId().equals(alarmNf.getId())) {

Loading…
Cancel
Save