fixed NPE

This commit is contained in:
YevhenBondarenko 2022-01-18 14:28:35 +02:00
parent 652071fdb7
commit 634bf0ff0f
3 changed files with 73 additions and 6 deletions

View File

@ -229,7 +229,7 @@ class AlarmRuleState {
long repeatingTimes = 0;
AlarmConditionSpec alarmConditionSpec = getSpec();
AlarmConditionSpecType specType = alarmConditionSpec.getType();
if(specType.equals(AlarmConditionSpecType.REPEATING)) {
if (specType.equals(AlarmConditionSpecType.REPEATING)) {
RepeatingAlarmConditionSpec repeating = (RepeatingAlarmConditionSpec) spec;
repeatingTimes = repeating.getPredicate().getDefaultValue();
@ -238,7 +238,13 @@ class AlarmRuleState {
repeating.getPredicate().getDynamicValue().getSourceAttribute() != null) {
EntityKeyValue repeatingKeyValue = getDynamicPredicateValue(data, repeating.getPredicate().getDynamicValue());
if (repeatingKeyValue != null) {
repeatingTimes = repeatingKeyValue.getLngValue();
var longValue = getLongValue(repeatingKeyValue);
if (longValue != null) {
repeatingTimes = longValue;
} else {
String sourceAttribute = repeating.getPredicate().getDynamicValue().getSourceAttribute();
throw new NumericParseException(String.format("could not parse attribute [%s: %s] from source!", sourceAttribute, getStrValue(repeatingKeyValue)));
}
}
}
}
@ -249,7 +255,7 @@ class AlarmRuleState {
long durationTimeInMs = 0;
AlarmConditionSpec alarmConditionSpec = getSpec();
AlarmConditionSpecType specType = alarmConditionSpec.getType();
if(specType.equals(AlarmConditionSpecType.DURATION)) {
if (specType.equals(AlarmConditionSpecType.DURATION)) {
DurationAlarmConditionSpec duration = (DurationAlarmConditionSpec) spec;
TimeUnit timeUnit = duration.getUnit();
@ -259,7 +265,13 @@ class AlarmRuleState {
duration.getPredicate().getDynamicValue().getSourceAttribute() != null) {
EntityKeyValue durationKeyValue = getDynamicPredicateValue(data, duration.getPredicate().getDynamicValue());
if (durationKeyValue != null) {
durationTimeInMs = timeUnit.toMillis(durationKeyValue.getLngValue());
var longValue = getLongValue(durationKeyValue);
if (longValue != null) {
durationTimeInMs = timeUnit.toMillis(longValue);
} else {
String sourceAttribute = duration.getPredicate().getDynamicValue().getSourceAttribute();
throw new NumericParseException(String.format("could not parse attribute [%s: %s] from source!", sourceAttribute, getStrValue(durationKeyValue)));
}
}
}
}
@ -545,4 +557,28 @@ class AlarmRuleState {
}
}
private static Long getLongValue(EntityKeyValue ekv) {
switch (ekv.getDataType()) {
case LONG:
return ekv.getLngValue();
case DOUBLE:
return ekv.getDblValue() != null ? ekv.getDblValue().longValue() : null;
case BOOLEAN:
return ekv.getBoolValue() != null ? (ekv.getBoolValue() ? 1 : 0L) : null;
case STRING:
try {
return Long.parseLong(ekv.getStrValue());
} catch (RuntimeException e) {
return null;
}
case JSON:
try {
return Long.parseLong(ekv.getJsonValue());
} catch (RuntimeException e) {
return null;
}
default:
return null;
}
}
}

View File

@ -51,6 +51,7 @@ import java.util.function.BiFunction;
@Slf4j
class AlarmState {
public static final String ERROR_MSG = "Failed to process alarm state for Device [%s]: %s";
private final ProfileState deviceProfile;
private final EntityId originator;
private DeviceProfileAlarm alarmDefinition;
@ -75,12 +76,20 @@ class AlarmState {
lastMsgMetaData = msg.getMetaData();
lastMsgQueueName = msg.getQueueName();
this.dataSnapshot = data;
return createOrClearAlarms(ctx, msg, data, update, AlarmRuleState::eval);
try {
return createOrClearAlarms(ctx, msg, data, update, AlarmRuleState::eval);
} catch (NumericParseException e) {
throw new RuntimeException(String.format(ERROR_MSG, originator.getId().toString(), e.getMessage()));
}
}
public boolean process(TbContext ctx, long ts) throws ExecutionException, InterruptedException {
initCurrentAlarm(ctx);
return createOrClearAlarms(ctx, null, ts, null, (alarmState, tsParam) -> alarmState.eval(tsParam, dataSnapshot));
try {
return createOrClearAlarms(ctx, null, ts, null, (alarmState, tsParam) -> alarmState.eval(tsParam, dataSnapshot));
} catch (NumericParseException e) {
throw new RuntimeException(String.format(ERROR_MSG, originator.getId().toString(), e.getMessage()));
}
}
public <T> boolean createOrClearAlarms(TbContext ctx, TbMsg msg, T data, SnapshotUpdate update, BiFunction<AlarmRuleState, T, AlarmEvalResult> evalFunction) {

View File

@ -0,0 +1,22 @@
/**
* Copyright © 2016-2022 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.rule.engine.profile;
public class NumericParseException extends RuntimeException {
public NumericParseException(String message) {
super(message);
}
}