Merge with release 3.4.4

This commit is contained in:
Andrii Shvaika 2023-02-07 18:47:38 +02:00
commit 8bd9f2e29c
19 changed files with 65 additions and 29 deletions

View File

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

View File

@ -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 {

View File

@ -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 {

View File

@ -38,7 +38,7 @@
<tb-postgres.docker.name>tb-postgres</tb-postgres.docker.name>
<tb-cassandra.docker.name>tb-cassandra</tb-cassandra.docker.name>
<pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
<pkg.upgradeVersion>3.4.3</pkg.upgradeVersion>
<pkg.upgradeVersion>3.4.4</pkg.upgradeVersion>
</properties>
<dependencies>

View File

@ -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,

View File

@ -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 {

View File

@ -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 <b>True</b> chain, otherwise <b>False</b> 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 <b>True</b> chain, otherwise, <b>False</b> 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 {

View File

@ -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 <b>True</b> chain, otherwise <b>False</b> 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 {

View File

@ -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,

View File

@ -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 <b>True</b> - send Message via <b>True</b> chain, otherwise <b>False</b> 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: <br/>" +
"Message payload can be accessed via <code>msg</code> property. For example <code>msg.temperature < 10;</code><br/>" +
"Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" +
"Message type can be accessed via <code>msgType</code> property.",

View File

@ -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 <code>msg</code> property. For example <code>msg.temperature < 10;</code><br/>" +
"Message metadata can be accessed via <code>metadata</code> property. For example <code>metadata.customerName === 'John';</code><br/>" +

View File

@ -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 <b>True</b> chain, otherwise <b>False</b> 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 {

View File

@ -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. </br>" +
"Configuration:</br></br>" +
"<ul>" +
"<li>Latitude key name - name of the message field that contains location latitude;</li>" +
"<li>Longitude key name - name of the message field that contains location longitude;</li>" +
"<li>Perimeter type - Polygon or Circle;</li>" +
"<li>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;</li>" +
"<li>Perimeter key name - name of the metadata key that stores perimeter information;</li>" +
"<li>For Polygon perimeter type: <ul>" +
" <li>Polygon definition - string that contains array of coordinates in the following format: [[lat1, lon1],[lat2, lon2],[lat3, lon3], ... , [latN, lonN]]</li>" +
"</ul></li>" +
"<li>For Circle perimeter type: <ul>" +
" <li>Center latitude - latitude of the circle perimeter center;</li>" +
" <li>Center longitude - longitude of the circle perimeter center;</li>" +
" <li>Range - value of the circle perimeter range, double-precision floating-point value;</li>" +
" <li>Range units - one of: Meter, Kilometer, Foot, Mile, Nautical Mile;</li>" +
"</ul></li></ul></br>" +
"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\"." +
"</br></br>" +
"Structure of the circle perimeter definition (stored in server-side attribute, for example):" +
"</br></br>" +
"{\"latitude\": 48.198618758582384, \"longitude\": 24.65322245153503, \"radius\": 100.0, \"radiusUnit\": \"METER\" }" +
"</br></br>" +
"Available radius units: METER, KILOMETER, FOOT, MILE, NAUTICAL_MILE;",
uiResources = {"static/rulenode/rulenode-core-config.js"},
configDirective = "tbFilterNodeGpsGeofencingConfig")
public class TbGpsGeofencingFilterNode extends AbstractGeofencingNode<TbGpsGeofencingFilterNodeConfiguration> {

View File

@ -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,

View File

@ -36,7 +36,7 @@ export class NavigationCardsWidgetSettingsComponent extends WidgetSettingsCompon
@ViewChild('filterItemAutocomplete') filterItemAutocomplete: MatAutocomplete;
@ViewChild('filterItemInput') filterItemInput: ElementRef<HTMLInputElement>;
filterItems: Array<string> = ['/devices', '/assets', '/deviceProfiles'];
filterItems: Array<string> = ['/devices', '/assets', '/profiles/deviceProfiles'];
separatorKeysCodes = [ENTER, COMMA, SEMICOLON];

View File

@ -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;
}

View File

@ -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',

View File

@ -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',