diff --git a/application/src/main/data/upgrade/3.4.3/schema_update.sql b/application/src/main/data/upgrade/3.4.4/schema_update.sql
similarity index 100%
rename from application/src/main/data/upgrade/3.4.3/schema_update.sql
rename to application/src/main/data/upgrade/3.4.4/schema_update.sql
diff --git a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
index d756541902..c0f4bd5cf4 100644
--- a/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
+++ b/application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
@@ -233,15 +233,17 @@ public class ThingsboardInstallService {
log.info("Upgrading ThingsBoard from version 3.4.1 to 3.4.2 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.4.1");
dataUpdateService.updateData("3.4.1");
+ case "3.4.2":
+ log.info("Upgrading ThingsBoard from version 3.4.2 to 3.4.3 ...");
case "3.4.3":
- log.info("Upgrading ThingsBoard from version 3.4.3 to 3.5.0 ...");
- databaseEntitiesUpgradeService.upgradeDatabase("3.4.3");
+ log.info("Upgrading ThingsBoard from version 3.4.3 to 3.4.4 ...");
+ case "3.4.4":
+ log.info("Upgrading ThingsBoard from version 3.4.4 to 3.5.0 ...");
+ databaseEntitiesUpgradeService.upgradeDatabase("3.4.4");
log.info("Updating system data...");
systemDataLoaderService.updateSystemWidgets();
break;
-
//TODO update CacheCleanupService on the next version upgrade
-
default:
throw new RuntimeException("Unable to upgrade ThingsBoard, unsupported fromVersion: " + upgradeFromVersion);
diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
index a4330d3972..b9ff5383b5 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
@@ -677,11 +677,11 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.error("Failed updating schema!!!", e);
}
break;
- case "3.4.3":
+ case "3.4.4":
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
log.info("Updating schema ...");
if (isOldSchema(conn, 3004002)) {
- schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.4.3", SCHEMA_UPDATE_SQL);
+ schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.4.4", SCHEMA_UPDATE_SQL);
loadSql(schemaUpdateFile, conn);
try {
diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java
index 228e0caf0c..54815ae973 100644
--- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java
+++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/DisableUIListeners.java
@@ -16,10 +16,12 @@
package org.thingsboard.server.msa;
import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface DisableUIListeners {
diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml
index 6a6aedc5b6..4b8439e0e9 100644
--- a/msa/tb/pom.xml
+++ b/msa/tb/pom.xml
@@ -38,7 +38,7 @@
tb-postgres
tb-cassandra
/usr/share/${pkg.name}
- 3.4.3
+ 3.4.4
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java
index d288062254..21e109e8f3 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbAssetTypeSwitchNode.java
@@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
@Slf4j
@RuleNode(
type = ComponentType.FILTER,
- name = "asset type switch",
+ name = "asset profile switch",
customRelations = true,
relationTypes = {},
configClazz = EmptyNodeConfiguration.class,
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java
index 04fd3aad25..ef7dca542f 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckAlarmStatusNode.java
@@ -42,7 +42,7 @@ import java.io.IOException;
configClazz = TbCheckAlarmStatusNodeConfig.class,
relationTypes = {"True", "False"},
nodeDescription = "Checks alarm status.",
- nodeDetails = "If the alarm status matches the specified one - msg is success if does not match - msg is failure.",
+ nodeDetails = "Checks the alarm status to match one of the specified statuses.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckAlarmStatusConfig")
public class TbCheckAlarmStatusNode implements TbNode {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java
index 26b8de5e8e..3853b3a62a 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckMessageNode.java
@@ -32,12 +32,13 @@ import java.util.Map;
@Slf4j
@RuleNode(
type = ComponentType.FILTER,
- name = "check existence fields",
+ name = "check fields presence",
relationTypes = {"True", "False"},
configClazz = TbCheckMessageNodeConfiguration.class,
- nodeDescription = "Checks the existence of the selected keys from message data and metadata.",
- nodeDetails = "If selected checkbox 'Check that all selected keys are present'\" and all keys in message data and metadata are exist - send Message via True chain, otherwise False chain is used.\n" +
- "Else if the checkbox is not selected, and at least one of the keys from data or metadata of the message exists - send Message via True chain, otherwise, False chain is used. ",
+ nodeDescription = "Checks the presence of the specified fields in the message and/or metadata.",
+ nodeDetails = "Checks the presence of the specified fields in the message and/or metadata. " +
+ "By default, the rule node checks that all specified fields need to be present. " +
+ "Uncheck the 'Check that all specified fields are present' if the presence of at least one field is sufficient.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckMessageConfig")
public class TbCheckMessageNode implements TbNode {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java
index 19a6c9ac5f..4a0d6b05e7 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbCheckRelationNode.java
@@ -46,10 +46,9 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
name = "check relation",
configClazz = TbCheckRelationNodeConfiguration.class,
relationTypes = {"True", "False"},
- nodeDescription = "Checks the relation from the selected entity to the originator of the message by type and direction" +
- " if 'Check for single entity' is set to true, otherwise rule node will check if exist" +
- " any relation to the originator of the message by type and direction.",
- nodeDetails = "If at least one relation exists - send Message via True chain, otherwise False chain is used.",
+ nodeDescription = "Checks the presence of the relation between the originator of the message and other entities.",
+ nodeDetails = "If 'check relation to specific entity' is selected, one must specify a related entity. " +
+ "Otherwise, the rule node checks the presence of a relation to any entity that matches the direction and relation type criteria.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeCheckRelationConfig")
public class TbCheckRelationNode implements TbNode {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java
index 104e25fdfc..16131ecc05 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbDeviceTypeSwitchNode.java
@@ -29,7 +29,7 @@ import org.thingsboard.server.common.data.plugin.ComponentType;
@Slf4j
@RuleNode(
type = ComponentType.FILTER,
- name = "device type switch",
+ name = "device profile switch",
customRelations = true,
relationTypes = {"default"},
configClazz = EmptyNodeConfiguration.class,
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
index b439c64abb..0bde9402a7 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsFilterNode.java
@@ -34,9 +34,10 @@ import static org.thingsboard.common.util.DonAsynchron.withCallback;
type = ComponentType.FILTER,
name = "script", relationTypes = {"True", "False"},
configClazz = TbJsFilterNodeConfiguration.class,
- nodeDescription = "Filter incoming messages using JS script",
- nodeDetails = "Evaluate incoming Message with configured JS condition. " +
- "If True - send Message via True chain, otherwise False chain is used." +
+ nodeDescription = "Filter incoming messages using TBEL or JS script",
+ nodeDetails = "Evaluates boolean function using incoming message. " +
+ "The function may be written using TBEL or plain JavaScript. " +
+ "Script function should return boolean value and accepts three parameters:
" +
"Message payload can be accessed via msg property. For example msg.temperature < 10;
" +
"Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
" +
"Message type can be accessed via msgType property.",
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
index 46422db94a..706978846a 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbJsSwitchNode.java
@@ -39,8 +39,8 @@ import java.util.Set;
name = "switch", customRelations = true,
relationTypes = {},
configClazz = TbJsSwitchNodeConfiguration.class,
- nodeDescription = "Route incoming Message to one or multiple output chains",
- nodeDetails = "Node executes configured JS script. Script should return array of next Chain names where Message should be routed. " +
+ nodeDescription = "Routes incoming message to one OR multiple output connections.",
+ nodeDetails = "Node executes configured TBEL(recommended) or JavaScript function that returns array of strings (connection names). " +
"If Array is empty - message not routed to next Node. " +
"Message payload can be accessed via msg property. For example msg.temperature < 10;
" +
"Message metadata can be accessed via metadata property. For example metadata.customerName === 'John';
" +
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java
index 5730de2b31..f4e13d761e 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/filter/TbOriginatorTypeFilterNode.java
@@ -32,8 +32,8 @@ import org.thingsboard.server.common.msg.TbMsg;
name = "entity type",
configClazz = TbOriginatorTypeFilterNodeConfiguration.class,
relationTypes = {"True", "False"},
- nodeDescription = "Filter incoming messages by message Originator Type",
- nodeDetails = "If the entity type of the incoming message originator is expected - send Message via True chain, otherwise False chain is used.",
+ nodeDescription = "Filter incoming messages by the type of message originator entity",
+ nodeDetails = "Checks that the entity type of the incoming message originator matches one of the values specified in the filter.",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeOriginatorTypeConfig")
public class TbOriginatorTypeFilterNode implements TbNode {
diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java
index 6df6bc1e8a..373118ebdd 100644
--- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java
+++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/geo/TbGpsGeofencingFilterNode.java
@@ -32,7 +32,32 @@ import org.thingsboard.server.common.msg.TbMsg;
configClazz = TbGpsGeofencingFilterNodeConfiguration.class,
relationTypes = {"True", "False"},
nodeDescription = "Filter incoming messages by GPS based geofencing",
- nodeDetails = "Extracts latitude and longitude parameters from incoming message and returns 'True' if they are inside configured perimeters, 'False' otherwise.",
+ nodeDetails = "Extracts latitude and longitude parameters from the incoming message and checks them according to configured perimeter. " +
+ "Configuration:" +
+ "" +
+ "- Latitude key name - name of the message field that contains location latitude;
" +
+ "- Longitude key name - name of the message field that contains location longitude;
" +
+ "- Perimeter type - Polygon or Circle;
" +
+ "- Fetch perimeter from message metadata - checkbox to load perimeter from message metadata; " +
+ " Enable if your perimeter is specific to device/asset and you store it as device/asset attribute;
" +
+ "- Perimeter key name - name of the metadata key that stores perimeter information;
" +
+ "- For Polygon perimeter type:
" +
+ " - Polygon definition - string that contains array of coordinates in the following format: [[lat1, lon1],[lat2, lon2],[lat3, lon3], ... , [latN, lonN]]
" +
+ "
" +
+ "- For Circle perimeter type:
" +
+ " - Center latitude - latitude of the circle perimeter center;
" +
+ " - Center longitude - longitude of the circle perimeter center;
" +
+ " - Range - value of the circle perimeter range, double-precision floating-point value;
" +
+ " - Range units - one of: Meter, Kilometer, Foot, Mile, Nautical Mile;
" +
+ "
" +
+ "Rule node will use default metadata key names, if the \"Fetch perimeter from message metadata\" is enabled and \"Perimeter key name\" is not configured. " +
+ "Default metadata key names for polygon perimeter type is \"perimeter\". Default metadata key names for circle perimeter are: \"centerLatitude\", \"centerLongitude\", \"range\", \"rangeUnit\"." +
+ "" +
+ "Structure of the circle perimeter definition (stored in server-side attribute, for example):" +
+ "" +
+ "{\"latitude\": 48.198618758582384, \"longitude\": 24.65322245153503, \"radius\": 100.0, \"radiusUnit\": \"METER\" }" +
+ "" +
+ "Available radius units: METER, KILOMETER, FOOT, MILE, NAUTICAL_MILE;",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeGpsGeofencingConfig")
public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode {
diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts
index c11cc03fda..3ed84b1b86 100644
--- a/ui-ngx/src/app/core/http/entity.service.ts
+++ b/ui-ngx/src/app/core/http/entity.service.ts
@@ -876,7 +876,7 @@ export class EntityService {
if (result.entityParamName && result.entityParamName.length) {
targetParams = stateParams[result.entityParamName];
}
- if (targetParams && targetParams.entityId) {
+ if (targetParams && targetParams.entityId && targetParams.entityName) {
currentEntity = {
id: targetParams.entityId.id,
entityType: targetParams.entityId.entityType as EntityType,
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts
index f5aa906463..f019a65040 100644
--- a/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/lib/settings/navigation/navigation-cards-widget-settings.component.ts
@@ -36,7 +36,7 @@ export class NavigationCardsWidgetSettingsComponent extends WidgetSettingsCompon
@ViewChild('filterItemAutocomplete') filterItemAutocomplete: MatAutocomplete;
@ViewChild('filterItemInput') filterItemInput: ElementRef;
- filterItems: Array = ['/devices', '/assets', '/deviceProfiles'];
+ filterItems: Array = ['/devices', '/assets', '/profiles/deviceProfiles'];
separatorKeysCodes = [ENTER, COMMA, SEMICOLON];
diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
index fe9f15260c..1f946e791b 100644
--- a/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
+++ b/ui-ngx/src/app/modules/home/components/widget/widget-component.service.ts
@@ -340,7 +340,7 @@ export class WidgetComponentService {
factories: modulesWithFactoriesList.map(mf => mf.factories).flat()
};
if (modules && modules.length) {
- resModulesWithFactories.modules.concat(modules);
+ resModulesWithFactories.modules = resModulesWithFactories.modules.concat(modules);
}
return resModulesWithFactories;
}
diff --git a/ui-ngx/src/app/shared/models/constants.ts b/ui-ngx/src/app/shared/models/constants.ts
index acdae938b5..bee7ebacc0 100644
--- a/ui-ngx/src/app/shared/models/constants.ts
+++ b/ui-ngx/src/app/shared/models/constants.ts
@@ -85,6 +85,9 @@ export const HelpLinks = {
ruleNodeGpsGeofencingFilter: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#gps-geofencing-filter-node',
ruleNodeJsFilter: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#script-filter-node',
ruleNodeJsSwitch: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#switch-node',
+ ruleNodeAssetProfileSwitch: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#asset-profile-switch',
+ ruleNodeDeviceProfileSwitch: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#device-profile-switch',
+ ruleNodeCheckAlarmStatus: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#check-alarm-status',
ruleNodeMessageTypeFilter: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#message-type-filter-node',
ruleNodeMessageTypeSwitch: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#message-type-switch-node',
ruleNodeOriginatorTypeFilter: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/filter-nodes/#originator-type-filter-node',
diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts
index bdaa3214c2..9d78a5ced8 100644
--- a/ui-ngx/src/app/shared/models/rule-node.models.ts
+++ b/ui-ngx/src/app/shared/models/rule-node.models.ts
@@ -422,6 +422,9 @@ const ruleNodeClazzHelpLinkMap = {
'org.thingsboard.rule.engine.geo.TbGpsGeofencingFilterNode': 'ruleNodeGpsGeofencingFilter',
'org.thingsboard.rule.engine.filter.TbJsFilterNode': 'ruleNodeJsFilter',
'org.thingsboard.rule.engine.filter.TbJsSwitchNode': 'ruleNodeJsSwitch',
+ 'org.thingsboard.rule.engine.filter.TbAssetTypeSwitchNode': 'ruleNodeAssetProfileSwitch',
+ 'org.thingsboard.rule.engine.filter.TbDeviceTypeSwitchNode': 'ruleNodeDeviceProfileSwitch',
+ 'org.thingsboard.rule.engine.filter.TbCheckAlarmStatusNode': 'ruleNodeCheckAlarmStatus',
'org.thingsboard.rule.engine.filter.TbMsgTypeFilterNode': 'ruleNodeMessageTypeFilter',
'org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode': 'ruleNodeMessageTypeSwitch',
'org.thingsboard.rule.engine.filter.TbOriginatorTypeFilterNode': 'ruleNodeOriginatorTypeFilter',