Commit 1daf5a44b5683a35b065f568e28498e414f95111
Committed by
Andrew Shvayka
1 parent
9531e891
alarm state improvements (added details to alarm from device profile details pattern)
Showing
1 changed file
with
47 additions
and
6 deletions
rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/AlarmState.java
... | ... | @@ -16,6 +16,7 @@ |
16 | 16 | package org.thingsboard.rule.engine.profile; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import com.fasterxml.jackson.databind.node.ObjectNode; | |
19 | 20 | import lombok.Data; |
20 | 21 | import lombok.extern.slf4j.Slf4j; |
21 | 22 | import org.thingsboard.rule.engine.action.TbAlarmResult; |
... | ... | @@ -29,6 +30,7 @@ import org.thingsboard.server.common.data.alarm.AlarmStatus; |
29 | 30 | import org.thingsboard.server.common.data.device.profile.DeviceProfileAlarm; |
30 | 31 | import org.thingsboard.server.common.data.id.EntityId; |
31 | 32 | import org.thingsboard.server.common.data.query.EntityKeyType; |
33 | +import org.thingsboard.server.common.data.query.KeyFilter; | |
32 | 34 | import org.thingsboard.server.common.msg.TbMsg; |
33 | 35 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
34 | 36 | import org.thingsboard.server.common.msg.queue.ServiceQueue; |
... | ... | @@ -74,7 +76,7 @@ class AlarmState { |
74 | 76 | |
75 | 77 | public <T> boolean createOrClearAlarms(TbContext ctx, T data, SnapshotUpdate update, BiFunction<AlarmRuleState, T, AlarmEvalResult> evalFunction) { |
76 | 78 | boolean stateUpdate = false; |
77 | - AlarmSeverity resultSeverity = null; | |
79 | + AlarmRuleState resultState = null; | |
78 | 80 | log.debug("[{}] processing update: {}", alarmDefinition.getId(), data); |
79 | 81 | for (AlarmRuleState state : createRulesSortedBySeverityDesc) { |
80 | 82 | if (!validateUpdate(update, state)) { |
... | ... | @@ -84,15 +86,15 @@ class AlarmState { |
84 | 86 | AlarmEvalResult evalResult = evalFunction.apply(state, data); |
85 | 87 | stateUpdate |= state.checkUpdate(); |
86 | 88 | if (AlarmEvalResult.TRUE.equals(evalResult)) { |
87 | - resultSeverity = state.getSeverity(); | |
89 | + resultState = state; | |
88 | 90 | break; |
89 | 91 | } else if (AlarmEvalResult.FALSE.equals(evalResult)) { |
90 | 92 | state.clear(); |
91 | 93 | stateUpdate |= state.checkUpdate(); |
92 | 94 | } |
93 | 95 | } |
94 | - if (resultSeverity != null) { | |
95 | - TbAlarmResult result = calculateAlarmResult(ctx, resultSeverity); | |
96 | + if (resultState != null) { | |
97 | + TbAlarmResult result = calculateAlarmResult(ctx, resultState, data); | |
96 | 98 | if (result != null) { |
97 | 99 | pushMsg(ctx, result); |
98 | 100 | } |
... | ... | @@ -187,7 +189,8 @@ class AlarmState { |
187 | 189 | } |
188 | 190 | } |
189 | 191 | |
190 | - private TbAlarmResult calculateAlarmResult(TbContext ctx, AlarmSeverity severity) { | |
192 | + private <T> TbAlarmResult calculateAlarmResult(TbContext ctx, AlarmRuleState ruleState, T data) { | |
193 | + AlarmSeverity severity = ruleState.getSeverity(); | |
191 | 194 | if (currentAlarm != null) { |
192 | 195 | // 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). |
193 | 196 | // Maybe we should fetch alarm every time? |
... | ... | @@ -213,7 +216,7 @@ class AlarmState { |
213 | 216 | currentAlarm.setSeverity(severity); |
214 | 217 | currentAlarm.setStartTs(System.currentTimeMillis()); |
215 | 218 | currentAlarm.setEndTs(currentAlarm.getStartTs()); |
216 | - currentAlarm.setDetails(JacksonUtil.OBJECT_MAPPER.createObjectNode()); | |
219 | + currentAlarm.setDetails(createDetails(ruleState, (DataSnapshot) data)); | |
217 | 220 | currentAlarm.setOriginator(originator); |
218 | 221 | currentAlarm.setTenantId(ctx.getTenantId()); |
219 | 222 | currentAlarm.setPropagate(alarmDefinition.isPropagate()); |
... | ... | @@ -226,6 +229,44 @@ class AlarmState { |
226 | 229 | } |
227 | 230 | } |
228 | 231 | |
232 | + private <T> JsonNode createDetails(AlarmRuleState ruleState, DataSnapshot dataSnapshot) { | |
233 | + ObjectNode details = JacksonUtil.OBJECT_MAPPER.createObjectNode(); | |
234 | + String alarmDetails = ruleState.getAlarmRule().getAlarmDetails(); | |
235 | + | |
236 | + if (alarmDetails != null) { | |
237 | + for (KeyFilter keyFilter : ruleState.getAlarmRule().getCondition().getCondition()) { | |
238 | + EntityKeyValue entityKeyValue = dataSnapshot.getValue(keyFilter.getKey()); | |
239 | + alarmDetails = alarmDetails.replaceAll(String.format("\\$\\{%s}", keyFilter.getKey().getKey()), getValueAsString(entityKeyValue)); | |
240 | + } | |
241 | + | |
242 | + details.put("data", alarmDetails); | |
243 | + } | |
244 | + | |
245 | + return details; | |
246 | + } | |
247 | + | |
248 | + private static String getValueAsString(EntityKeyValue entityKeyValue) { | |
249 | + Object result = null; | |
250 | + switch (entityKeyValue.getDataType()) { | |
251 | + case STRING: | |
252 | + result = entityKeyValue.getStrValue(); | |
253 | + break; | |
254 | + case JSON: | |
255 | + result = entityKeyValue.getJsonValue(); | |
256 | + break; | |
257 | + case LONG: | |
258 | + result = String.valueOf(entityKeyValue.getLngValue()); | |
259 | + break; | |
260 | + case DOUBLE: | |
261 | + result = String.valueOf(entityKeyValue.getDblValue()); | |
262 | + break; | |
263 | + case BOOLEAN: | |
264 | + result = String.valueOf(entityKeyValue.getBoolValue()); | |
265 | + break; | |
266 | + } | |
267 | + return String.valueOf(result); | |
268 | + } | |
269 | + | |
229 | 270 | public boolean processAlarmClear(TbContext ctx, Alarm alarmNf) { |
230 | 271 | boolean updated = false; |
231 | 272 | if (currentAlarm != null && currentAlarm.getId().equals(alarmNf.getId())) { | ... | ... |