fixed functions

This commit is contained in:
IrynaMatveieva 2025-02-26 15:22:42 +02:00
parent a52c578ecd
commit 72f26d9fe2
2 changed files with 100 additions and 36 deletions

View File

@ -25,7 +25,6 @@ import org.thingsboard.script.api.tbel.TbelCfTsDoubleVal;
import org.thingsboard.script.api.tbel.TbelCfTsRollingArg;
import org.thingsboard.server.common.data.kv.KvEntry;
import org.thingsboard.server.common.data.kv.TsKvEntry;
import org.thingsboard.server.exception.CalculatedFieldStateException;
import java.util.ArrayList;
import java.util.List;
@ -116,10 +115,11 @@ public class TsRollingArgumentEntry implements ArgumentEntry {
case STRING -> value.getStrValue().ifPresent(aString -> tsRecords.put(ts, Double.parseDouble(aString)));
case JSON -> value.getJsonValue().ifPresent(aString -> tsRecords.put(ts, Double.parseDouble(aString)));
}
cleanupExpiredRecords();
} catch (Exception e) {
tsRecords.put(ts, Double.NaN);
log.debug("Invalid value '{}' for time series rolling arguments. Only numeric values are supported.", value.getValue());
} finally {
cleanupExpiredRecords();
}
}

View File

@ -61,14 +61,18 @@ public class TbelCfTsRollingArg implements TbelCfArg, Iterable<TbelCfTsDoubleVal
}
public double max() {
return max(true);
}
public double max(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
double max = Double.MIN_VALUE;
for (TbelCfTsDoubleVal value : values) {
double val = value.getValue();
if (Double.isNaN(val)) {
if (!ignoreNaN && Double.isNaN(val)) {
return val;
}
if (max < val) {
@ -79,14 +83,18 @@ public class TbelCfTsRollingArg implements TbelCfArg, Iterable<TbelCfTsDoubleVal
}
public double min() {
return min(true);
}
public double min(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
double min = Double.MAX_VALUE;
for (TbelCfTsDoubleVal value : values) {
double val = value.getValue();
if (Double.isNaN(val)) {
if (!ignoreNaN && Double.isNaN(val)) {
return Double.NaN;
}
if (min > val) {
@ -97,21 +105,28 @@ public class TbelCfTsRollingArg implements TbelCfArg, Iterable<TbelCfTsDoubleVal
}
public double mean() {
return mean(true);
}
public double mean(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
double sum = sum();
return Double.isNaN(sum) ? Double.NaN : sum / values.size();
return sum(ignoreNaN) / count(ignoreNaN);
}
public double std() {
return std(true);
}
public double std(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
double mean = mean();
if (Double.isNaN(mean)) {
double mean = mean(ignoreNaN);
if (!ignoreNaN && Double.isNaN(mean)) {
return Double.NaN;
}
@ -119,25 +134,35 @@ public class TbelCfTsRollingArg implements TbelCfArg, Iterable<TbelCfTsDoubleVal
for (TbelCfTsDoubleVal value : values) {
double val = value.getValue();
if (Double.isNaN(val)) {
return Double.NaN;
if (!ignoreNaN) {
return Double.NaN;
}
} else {
sum += Math.pow(val - mean, 2);
}
sum += Math.pow(val - mean, 2);
}
return Math.sqrt(sum / values.size());
return Math.sqrt(sum / count(ignoreNaN));
}
public double median() {
return median(true);
}
public double median(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
List<Double> sortedValues = new ArrayList<>();
for (TbelCfTsDoubleVal value : values) {
double val = value.getValue();
if (Double.isNaN(val)) {
return Double.NaN;
if (!ignoreNaN) {
return Double.NaN;
}
} else {
sortedValues.add(val);
}
sortedValues.add(val);
}
Collections.sort(sortedValues);
@ -147,51 +172,90 @@ public class TbelCfTsRollingArg implements TbelCfArg, Iterable<TbelCfTsDoubleVal
: (sortedValues.get(size / 2 - 1) + sortedValues.get(size / 2)) / 2.0;
}
public double count() {
return hasNaN() ? Double.NaN : values.size();
public int count() {
return count(true);
}
public int count(boolean ignoreNaN) {
int count = 0;
if (ignoreNaN) {
for (TbelCfTsDoubleVal value : values) {
if (!Double.isNaN(value.getValue())) {
count++;
}
}
return count;
}
return values.size();
}
public double last() {
return last(true);
}
public double last(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
return hasNaN() ? Double.NaN : values.get(values.size() - 1).getValue();
double value = values.get(values.size() - 1).getValue();
if (!Double.isNaN(value) || !ignoreNaN) {
return value;
}
for (int i = values.size() - 2; i >= 0; i--) {
double prevValue = values.get(i).getValue();
if (!Double.isNaN(prevValue)) {
return prevValue;
}
}
throw new IllegalArgumentException("Rolling argument values are empty.");
}
public double first() {
return first(true);
}
public double first(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
return hasNaN() ? Double.NaN : values.get(0).getValue();
double firstValue = values.get(0).getValue();
if (!Double.isNaN(firstValue) || !ignoreNaN) {
return firstValue;
}
for (int i = 1; i < values.size(); i++) {
double nextValue = values.get(i).getValue();
if (!Double.isNaN(nextValue)) {
return nextValue;
}
}
throw new IllegalArgumentException("Rolling argument values are empty.");
}
public double sum() {
return sum(true);
}
public double sum(boolean ignoreNaN) {
if (values.isEmpty()) {
return 0;
throw new IllegalArgumentException("Rolling argument values are empty.");
}
double sum = 0;
for (TbelCfTsDoubleVal value : values) {
double val = value.getValue();
if (Double.isNaN(val)) {
return Double.NaN;
if (!ignoreNaN) {
return Double.NaN;
}
} else {
sum += val;
}
sum += val;
}
return sum;
}
private boolean hasNaN() {
for (TbelCfTsDoubleVal value : values) {
if (Double.isNaN(value.getValue())) {
return true;
}
}
return false;
}
@JsonIgnore
public int getSize() {
return values.size();