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);