diff --git a/common/actor/src/main/java/org/thingsboard/server/actors/DefaultTbActorSystem.java b/common/actor/src/main/java/org/thingsboard/server/actors/DefaultTbActorSystem.java
index 1588f0d2b5..7fad1a329c 100644
--- a/common/actor/src/main/java/org/thingsboard/server/actors/DefaultTbActorSystem.java
+++ b/common/actor/src/main/java/org/thingsboard/server/actors/DefaultTbActorSystem.java
@@ -215,6 +215,7 @@ public class DefaultTbActorSystem implements TbActorSystem {
@Override
public void stop() {
+ actors.values().forEach(mailbox -> Optional.ofNullable(mailbox).ifPresent(m -> m.destroy(null)));
dispatchers.values().forEach(dispatcher -> {
dispatcher.getExecutor().shutdown();
try {
@@ -226,7 +227,6 @@ public class DefaultTbActorSystem implements TbActorSystem {
if (scheduler != null) {
scheduler.shutdownNow();
}
- actors.values().forEach(mailbox -> Optional.ofNullable(mailbox).ifPresent(m -> m.destroy(null)));
actors.clear();
}
diff --git a/common/script/script-api/pom.xml b/common/script/script-api/pom.xml
index 3655692217..4b6c1ee21c 100644
--- a/common/script/script-api/pom.xml
+++ b/common/script/script-api/pom.xml
@@ -48,6 +48,10 @@
org.thingsboard.common
util
+
+ org.thingsboard.rule-engine
+ rule-engine-components
+
org.javadelight
delight-nashorn-sandbox
diff --git a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java
index 95fff48883..ecb47668f3 100644
--- a/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java
+++ b/common/script/script-api/src/main/java/org/thingsboard/script/api/tbel/TbUtils.java
@@ -15,6 +15,7 @@
*/
package org.thingsboard.script.api.tbel;
+import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.primitives.Bytes;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
@@ -23,6 +24,10 @@ import org.mvel2.ParserConfiguration;
import org.mvel2.execution.ExecutionArrayList;
import org.mvel2.execution.ExecutionHashMap;
import org.mvel2.util.MethodStub;
+import org.thingsboard.common.util.JacksonUtil;
+import org.thingsboard.rule.engine.geo.Coordinates;
+import org.thingsboard.rule.engine.geo.GeoUtil;
+import org.thingsboard.rule.engine.geo.RangeUnit;
import org.thingsboard.server.common.data.StringUtils;
import java.io.IOException;
@@ -371,6 +376,10 @@ public class TbUtils {
byte[].class, int.class)));
parserConfig.addImport("parseBinaryArrayToInt", new MethodStub(TbUtils.class.getMethod("parseBinaryArrayToInt",
byte[].class, int.class, int.class)));
+ parserConfig.addImport("isInsidePolygon", new MethodStub(TbUtils.class.getMethod("isInsidePolygon",
+ double.class, double.class, String.class)));
+ parserConfig.addImport("isInsideCircle", new MethodStub(TbUtils.class.getMethod("isInsideCircle",
+ double.class, double.class, String.class)));
}
public static String btoa(String input) {
@@ -1437,6 +1446,22 @@ public class TbUtils {
return result;
}
+ public static boolean isInsidePolygon(double latitude, double longitude, String perimeter) {
+ return GeoUtil.contains(perimeter, new Coordinates(latitude, longitude));
+ }
+
+ public static boolean isInsideCircle(double latitude, double longitude, String perimeter) {
+ JsonNode perimeterJson = JacksonUtil.toJsonNode(perimeter);
+ double centerLatitude = Double.parseDouble(perimeterJson.get("latitude").asText());
+ double centerLongitude = Double.parseDouble(perimeterJson.get("longitude").asText());
+ double range = Double.parseDouble(perimeterJson.get("radius").asText());
+ RangeUnit rangeUnit = perimeterJson.has("radiusUnit") ? RangeUnit.valueOf(perimeterJson.get("radiusUnit").asText()) : RangeUnit.METER;
+
+ Coordinates entityCoordinates = new Coordinates(latitude, longitude);
+ Coordinates perimeterCoordinates = new Coordinates(centerLatitude, centerLongitude);
+ return range > GeoUtil.distance(entityCoordinates, perimeterCoordinates, rangeUnit);
+ }
+
private static byte isValidIntegerToByte(Integer val) {
if (val > 255 || val < -128) {
throw new NumberFormatException("The value '" + val + "' could not be correctly converted to a byte. " +
diff --git a/ui-ngx/src/app/shared/models/ace/tbel-utils.models.ts b/ui-ngx/src/app/shared/models/ace/tbel-utils.models.ts
index f29ae083be..c988f5ca0a 100644
--- a/ui-ngx/src/app/shared/models/ace/tbel-utils.models.ts
+++ b/ui-ngx/src/app/shared/models/ace/tbel-utils.models.ts
@@ -1245,6 +1245,56 @@ const tbelEditorCompletions:TbEditorCompletions = {
type: 'boolean'
}
},
+ isInsidePolygon: {
+ meta: 'function',
+ description: 'Checks if a given point is inside a polygon.',
+ args: [
+ {
+ name: 'latitude',
+ description: 'The latitude of the point',
+ type: 'number'
+ },
+ {
+ name: 'longitude',
+ description: 'The longitude of the point',
+ type: 'number'
+ },
+ {
+ name: 'perimeter',
+ description: 'The polygon perimeter represented as a string',
+ type: 'string'
+ }
+ ],
+ return: {
+ description: 'True if the point is inside the polygon, false otherwise.',
+ type: 'boolean'
+ }
+ },
+ isInsideCircle: {
+ meta: 'function',
+ description: 'Checks if a given point is inside a circular area.',
+ args: [
+ {
+ name: 'latitude',
+ description: 'The latitude of the point',
+ type: 'number'
+ },
+ {
+ name: 'longitude',
+ description: 'The longitude of the point',
+ type: 'number'
+ },
+ {
+ name: 'perimeter',
+ description: 'A string representation of the circle, containing center coordinates and radius',
+ type: 'string'
+ }
+ ],
+ return: {
+ description: 'True if the point is inside the circle, false otherwise.',
+ type: 'boolean'
+ }
+ }
}
export const tbelUtilsAutocompletes = new TbEditorCompleter(tbelEditorCompletions);