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:

" + + "
" + + "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',