From 928f8f84b642be50c8e829445bb31dab5bd224c2 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Tue, 11 Dec 2018 15:44:59 +0200 Subject: [PATCH 01/27] added TbRelationActionNodes (#1287) * added TbRelationActionNodes * refactoring RelationActionNodes * update license header * fix TbAssignToCustomerNode * refactoring relation action node * refactoring CreateRelationNode * update license header * refactoring TbCreateRelationNode * refactoring TbCreateRelationNode * refactoring TbCreateRelationNode * update license header * refactoring TbCreateRelationNode & TbAssignToCustomerNode --- ...stractCustomerActionNodeConfiguration.java | 3 - .../action/TbAbstractRelationActionNode.java | 222 ++++++++++++++++++ ...stractRelationActionNodeConfiguration.java | 32 +++ .../engine/action/TbAssignToCustomerNode.java | 4 + .../engine/action/TbCreateRelationNode.java | 156 ++++++++++++ .../TbCreateRelationNodeConfiguration.java | 37 +++ .../engine/action/TbDeleteRelationNode.java | 74 ++++++ .../TbDeleteRelationNodeConfiguration.java | 35 +++ .../rule/engine/util/EntityContainer.java | 28 +++ .../static/rulenode/rulenode-core-config.js | 7 +- 10 files changed, 592 insertions(+), 6 deletions(-) create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNode.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNodeConfiguration.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNode.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeConfiguration.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeConfiguration.java create mode 100644 rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntityContainer.java diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractCustomerActionNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractCustomerActionNodeConfiguration.java index 3f587b5401..86b8cb8e49 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractCustomerActionNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractCustomerActionNodeConfiguration.java @@ -17,9 +17,6 @@ package org.thingsboard.rule.engine.action; import lombok.Data; -/** - * Created by igor on 6/1/18. - */ @Data public abstract class TbAbstractCustomerActionNodeConfiguration { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNode.java new file mode 100644 index 0000000000..c3608fcf21 --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNode.java @@ -0,0 +1,222 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.action; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; +import org.thingsboard.rule.engine.util.EntityContainer; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.DashboardInfo; +import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityIdFactory; +import org.thingsboard.server.common.data.page.TextPageData; +import org.thingsboard.server.common.data.page.TextPageLink; +import org.thingsboard.server.common.data.relation.EntitySearchDirection; +import org.thingsboard.server.common.msg.TbMsg; +import org.thingsboard.server.dao.asset.AssetService; +import org.thingsboard.server.dao.customer.CustomerService; +import org.thingsboard.server.dao.dashboard.DashboardService; +import org.thingsboard.server.dao.device.DeviceService; +import org.thingsboard.server.dao.entityview.EntityViewService; + +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import static org.thingsboard.rule.engine.api.TbRelationTypes.FAILURE; +import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; +import static org.thingsboard.rule.engine.api.util.DonAsynchron.withCallback; + +@Slf4j +public abstract class TbAbstractRelationActionNode implements TbNode { + + protected C config; + protected EntityId fromId; + protected EntityId toId; + + private LoadingCache entityIdCache; + + @Override + public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { + this.config = loadEntityNodeActionConfig(configuration); + CacheBuilder cacheBuilder = CacheBuilder.newBuilder(); + if (this.config.getEntityCacheExpiration() > 0) { + cacheBuilder.expireAfterWrite(this.config.getEntityCacheExpiration(), TimeUnit.SECONDS); + } + entityIdCache = cacheBuilder + .build(new EntityCacheLoader(ctx, createEntityIfNotExists())); + } + + @Override + public void onMsg(TbContext ctx, TbMsg msg) { + withCallback(processEntityRelationAction(ctx, msg), + filterResult -> ctx.tellNext(msg, filterResult ? SUCCESS : FAILURE), t -> ctx.tellFailure(msg, t), ctx.getDbCallbackExecutor()); + } + + @Override + public void destroy() { + } + + private ListenableFuture processEntityRelationAction(TbContext ctx, TbMsg msg) { + return Futures.transformAsync(getEntity(ctx, msg), entityContainer -> doProcessEntityRelationAction(ctx, msg, entityContainer)); + } + + protected abstract boolean createEntityIfNotExists(); + + protected abstract ListenableFuture doProcessEntityRelationAction(TbContext ctx, TbMsg msg, EntityContainer entityContainer); + + protected abstract C loadEntityNodeActionConfig(TbNodeConfiguration configuration) throws TbNodeException; + + protected ListenableFuture getEntity(TbContext ctx, TbMsg msg) { + String entityName = TbNodeUtils.processPattern(this.config.getEntityNamePattern(), msg.getMetaData()); + String type = null; + if (this.config.getEntityTypePattern() != null) { + type = TbNodeUtils.processPattern(this.config.getEntityTypePattern(), msg.getMetaData()); + } + EntityType entityType = EntityType.valueOf(this.config.getEntityType()); + Entitykey key = new Entitykey(entityName, type, entityType); + return ctx.getDbCallbackExecutor().executeAsync(() -> { + EntityContainer entityContainer = entityIdCache.get(key); + if (entityContainer.getEntityId() == null) { + throw new RuntimeException("No entity found with type '" + key.getEntityType() + " ' and name '" + key.getEntityName() + "'."); + } + return entityContainer; + }); + } + + protected void processSearchDirection(TbMsg msg, EntityContainer entityContainer) { + if (EntitySearchDirection.FROM.name().equals(config.getDirection())) { + fromId = EntityIdFactory.getByTypeAndId(entityContainer.getEntityType().name(), entityContainer.getEntityId().toString()); + toId = msg.getOriginator(); + } else { + toId = EntityIdFactory.getByTypeAndId(entityContainer.getEntityType().name(), entityContainer.getEntityId().toString()); + fromId = msg.getOriginator(); + } + } + + @Data + @AllArgsConstructor + private static class Entitykey { + private String entityName; + private String type; + private EntityType entityType; + } + + private static class EntityCacheLoader extends CacheLoader { + + private final TbContext ctx; + private final boolean createIfNotExists; + + private EntityCacheLoader(TbContext ctx, boolean createIfNotExists) { + this.ctx = ctx; + this.createIfNotExists = createIfNotExists; + } + + @Override + public EntityContainer load(Entitykey key) { + return loadEntity(key); + } + + private EntityContainer loadEntity(Entitykey entitykey) { + EntityType type = entitykey.getEntityType(); + EntityContainer targetEntity = new EntityContainer(); + targetEntity.setEntityType(type); + switch (type) { + case DEVICE: + DeviceService deviceService = ctx.getDeviceService(); + Device device = deviceService.findDeviceByTenantIdAndName(ctx.getTenantId(), entitykey.getEntityName()); + if (device != null) { + targetEntity.setEntityId(device.getId()); + } else if (createIfNotExists) { + Device newDevice = new Device(); + newDevice.setName(entitykey.getEntityName()); + newDevice.setType(entitykey.getType()); + newDevice.setTenantId(ctx.getTenantId()); + Device savedDevice = deviceService.saveDevice(newDevice); + targetEntity.setEntityId(savedDevice.getId()); + } + break; + case ASSET: + AssetService assetService = ctx.getAssetService(); + Asset asset = assetService.findAssetByTenantIdAndName(ctx.getTenantId(), entitykey.getEntityName()); + if (asset != null) { + targetEntity.setEntityId(asset.getId()); + } else if (createIfNotExists) { + Asset newAsset = new Asset(); + newAsset.setName(entitykey.getEntityName()); + newAsset.setType(entitykey.getType()); + newAsset.setTenantId(ctx.getTenantId()); + Asset savedAsset = assetService.saveAsset(newAsset); + targetEntity.setEntityId(savedAsset.getId()); + } + break; + case CUSTOMER: + CustomerService customerService = ctx.getCustomerService(); + Optional customerOptional = customerService.findCustomerByTenantIdAndTitle(ctx.getTenantId(), entitykey.getEntityName()); + if (customerOptional.isPresent()) { + targetEntity.setEntityId(customerOptional.get().getId()); + } else if (createIfNotExists) { + Customer newCustomer = new Customer(); + newCustomer.setTitle(entitykey.getEntityName()); + newCustomer.setTenantId(ctx.getTenantId()); + Customer savedCustomer = customerService.saveCustomer(newCustomer); + targetEntity.setEntityId(savedCustomer.getId()); + } + break; + case TENANT: + targetEntity.setEntityId(ctx.getTenantId()); + break; + case ENTITY_VIEW: + EntityViewService entityViewService = ctx.getEntityViewService(); + EntityView entityView = entityViewService.findEntityViewByTenantIdAndName(ctx.getTenantId(), entitykey.getEntityName()); + if (entityView != null) { + targetEntity.setEntityId(entityView.getId()); + } + break; + case DASHBOARD: + DashboardService dashboardService = ctx.getDashboardService(); + TextPageData dashboardInfoTextPageData = dashboardService.findDashboardsByTenantId(ctx.getTenantId(), new TextPageLink(200, entitykey.getEntityName())); + for (DashboardInfo dashboardInfo : dashboardInfoTextPageData.getData()) { + if (dashboardInfo.getTitle().equals(entitykey.getEntityName())) { + targetEntity.setEntityId(dashboardInfo.getId()); + } + } + break; + default: + return targetEntity; + } + return targetEntity; + } + + + } + + +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNodeConfiguration.java new file mode 100644 index 0000000000..761dc43d97 --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAbstractRelationActionNodeConfiguration.java @@ -0,0 +1,32 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.action; + +import lombok.Data; + +@Data +public abstract class TbAbstractRelationActionNodeConfiguration { + + private String direction; + private String relationType; + + private String entityType; + private String entityNamePattern; + private String entityTypePattern; + + private long entityCacheExpiration; + +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java index 7c50aad092..70b5bd39e5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbAssignToCustomerNode.java @@ -52,6 +52,10 @@ public class TbAssignToCustomerNode extends TbAbstractCustomerActionNode { + + @Override + protected TbCreateRelationNodeConfiguration loadEntityNodeActionConfig(TbNodeConfiguration configuration) throws TbNodeException { + return TbNodeUtils.convert(configuration, TbCreateRelationNodeConfiguration.class); + } + + @Override + protected boolean createEntityIfNotExists() { + return config.isCreateEntityIfNotExists(); + } + + @Override + protected ListenableFuture doProcessEntityRelationAction(TbContext ctx, TbMsg msg, EntityContainer entity) { + return createIfAbsent(ctx, msg, entity); + } + + private ListenableFuture createIfAbsent(TbContext ctx, TbMsg msg, EntityContainer entityContainer) { + processSearchDirection(msg, entityContainer); + return Futures.transformAsync(ctx.getRelationService().checkRelation(ctx.getTenantId(), fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON), + result -> { + if (!result) { + return processCreateRelation(ctx, entityContainer); + } + return Futures.immediateFuture(true); + }); + } + + private ListenableFuture processCreateRelation(TbContext ctx, EntityContainer entityContainer) { + switch (entityContainer.getEntityType()) { + case ASSET: + return processAsset(ctx, entityContainer); + case DEVICE: + return processDevice(ctx, entityContainer); + case CUSTOMER: + return processCustomer(ctx, entityContainer); + case DASHBOARD: + return processDashboard(ctx, entityContainer); + case ENTITY_VIEW: + return processView(ctx, entityContainer); + case TENANT: + return processTenant(ctx, entityContainer); + } + return Futures.immediateFuture(true); + } + + private ListenableFuture processView(TbContext ctx, EntityContainer entityContainer) { + return Futures.transformAsync(ctx.getEntityViewService().findEntityViewByIdAsync(ctx.getTenantId(), new EntityViewId(entityContainer.getEntityId().getId())), entityView -> { + if (entityView != null) { + return ctx.getRelationService().saveRelationAsync(ctx.getTenantId(), new EntityRelation(fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON)); + } else { + return Futures.immediateFuture(true); + } + }); + } + + private ListenableFuture processDevice(TbContext ctx, EntityContainer entityContainer) { + return Futures.transformAsync(ctx.getDeviceService().findDeviceByIdAsync(ctx.getTenantId(), new DeviceId(entityContainer.getEntityId().getId())), device -> { + if (device != null) { + return ctx.getRelationService().saveRelationAsync(ctx.getTenantId(), new EntityRelation(fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON)); + } else { + return Futures.immediateFuture(true); + } + }); + } + + private ListenableFuture processAsset(TbContext ctx, EntityContainer entityContainer) { + return Futures.transformAsync(ctx.getAssetService().findAssetByIdAsync(ctx.getTenantId(), new AssetId(entityContainer.getEntityId().getId())), asset -> { + if (asset != null) { + return ctx.getRelationService().saveRelationAsync(ctx.getTenantId(), new EntityRelation(fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON)); + } else { + return Futures.immediateFuture(true); + } + }); + } + + private ListenableFuture processCustomer(TbContext ctx, EntityContainer entityContainer) { + return Futures.transformAsync(ctx.getCustomerService().findCustomerByIdAsync(ctx.getTenantId(), new CustomerId(entityContainer.getEntityId().getId())), customer -> { + if (customer != null) { + return ctx.getRelationService().saveRelationAsync(ctx.getTenantId(), new EntityRelation(fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON)); + } else { + return Futures.immediateFuture(true); + } + }); + } + + private ListenableFuture processDashboard(TbContext ctx, EntityContainer entityContainer) { + return Futures.transformAsync(ctx.getDashboardService().findDashboardByIdAsync(ctx.getTenantId(), new DashboardId(entityContainer.getEntityId().getId())), dashboard -> { + if (dashboard != null) { + return ctx.getRelationService().saveRelationAsync(ctx.getTenantId(), new EntityRelation(fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON)); + } else { + return Futures.immediateFuture(true); + } + }); + } + + private ListenableFuture processTenant(TbContext ctx, EntityContainer entityContainer) { + return Futures.transformAsync(ctx.getTenantService().findTenantByIdAsync(ctx.getTenantId(), new TenantId(entityContainer.getEntityId().getId())), tenant -> { + if (tenant != null) { + return ctx.getRelationService().saveRelationAsync(ctx.getTenantId(), new EntityRelation(fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON)); + } else { + return Futures.immediateFuture(true); + } + }); + } + +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeConfiguration.java new file mode 100644 index 0000000000..83d267aca1 --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateRelationNodeConfiguration.java @@ -0,0 +1,37 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.action; + +import lombok.Data; +import org.thingsboard.rule.engine.api.NodeConfiguration; +import org.thingsboard.server.common.data.relation.EntitySearchDirection; + +@Data +public class TbCreateRelationNodeConfiguration extends TbAbstractRelationActionNodeConfiguration implements NodeConfiguration { + + private boolean createEntityIfNotExists; + + @Override + public TbCreateRelationNodeConfiguration defaultConfiguration() { + TbCreateRelationNodeConfiguration configuration = new TbCreateRelationNodeConfiguration(); + configuration.setDirection(EntitySearchDirection.FROM.name()); + configuration.setRelationType("Contains"); + configuration.setEntityNamePattern(""); + configuration.setEntityCacheExpiration(300); + configuration.setCreateEntityIfNotExists(false); + return configuration; + } +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java new file mode 100644 index 0000000000..c339ffce17 --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNode.java @@ -0,0 +1,74 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.action; + +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import lombok.extern.slf4j.Slf4j; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.rule.engine.api.util.TbNodeUtils; +import org.thingsboard.rule.engine.util.EntityContainer; +import org.thingsboard.server.common.data.plugin.ComponentType; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.common.msg.TbMsg; + +@Slf4j +@RuleNode( + type = ComponentType.ACTION, + name = "delete relation", + configClazz = TbDeleteRelationNodeConfiguration.class, + nodeDescription = "Finds target Entity by entity name pattern and then delete a relation to Originator Entity by type and direction.", + nodeDetails = "If the relation successfully deleted - Message send via Success chain, otherwise Failure chain will be used.", + uiResources = {"static/rulenode/rulenode-core-config.js"}, + configDirective = "tbActionNodeDeleteRelationConfig", + icon = "remove_circle" +) +public class TbDeleteRelationNode extends TbAbstractRelationActionNode { + + @Override + protected TbDeleteRelationNodeConfiguration loadEntityNodeActionConfig(TbNodeConfiguration configuration) throws TbNodeException { + return TbNodeUtils.convert(configuration, TbDeleteRelationNodeConfiguration.class); + } + + @Override + protected boolean createEntityIfNotExists() { + return false; + } + + @Override + protected ListenableFuture doProcessEntityRelationAction(TbContext ctx, TbMsg msg, EntityContainer entityContainer) { + return deleteIfExist(ctx, msg, entityContainer); + } + + private ListenableFuture deleteIfExist(TbContext ctx, TbMsg msg, EntityContainer entityContainer) { + processSearchDirection(msg, entityContainer); + return Futures.transformAsync(ctx.getRelationService().checkRelation(ctx.getTenantId(), fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON), + result -> { + if (result) { + return processDeleteRelation(ctx); + } + return Futures.immediateFuture(true); + }); + } + + private ListenableFuture processDeleteRelation(TbContext ctx) { + return ctx.getRelationService().deleteRelationAsync(ctx.getTenantId(), fromId, toId, config.getRelationType(), RelationTypeGroup.COMMON); + } + +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeConfiguration.java new file mode 100644 index 0000000000..f78640420b --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbDeleteRelationNodeConfiguration.java @@ -0,0 +1,35 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.action; + +import lombok.Data; +import org.thingsboard.rule.engine.api.NodeConfiguration; +import org.thingsboard.server.common.data.relation.EntitySearchDirection; + +@Data +public class TbDeleteRelationNodeConfiguration extends TbAbstractRelationActionNodeConfiguration implements NodeConfiguration { + + + @Override + public TbDeleteRelationNodeConfiguration defaultConfiguration() { + TbDeleteRelationNodeConfiguration configuration = new TbDeleteRelationNodeConfiguration(); + configuration.setDirection(EntitySearchDirection.FROM.name()); + configuration.setRelationType("Contains"); + configuration.setEntityNamePattern(""); + configuration.setEntityCacheExpiration(300); + return configuration; + } +} diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntityContainer.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntityContainer.java new file mode 100644 index 0000000000..33c6a49927 --- /dev/null +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/util/EntityContainer.java @@ -0,0 +1,28 @@ +/** + * Copyright © 2016-2018 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.rule.engine.util; + +import lombok.Data; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.id.EntityId; + +@Data +public class EntityContainer { + + private EntityId entityId; + private EntityType entityType; + +} \ No newline at end of file diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 8151e7d385..3101b87f77 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,4 +1,5 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,a){r.apply(this,[e,t,a].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(85)},function(e,t){},1,1,1,1,function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
{{ 'tb.rulenode.create-customer-if-not-exists' | translate }}
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{scope.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
{{ severity.name | translate}}
tb.rulenode.alarm-severity-required
{{ 'tb.rulenode.propagate' | translate }}
"},function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.bootstrap-servers-required
tb.rulenode.min-retries-message
tb.rulenode.min-batch-size-bytes-message
tb.rulenode.min-linger-ms-message
tb.rulenode.min-buffer-memory-bytes-message
{{ ackValue }}
tb.rulenode.key-serializer-required
tb.rulenode.value-serializer-required
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-to-string-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.mqtt-topic-pattern-hint
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
tb.rulenode.connect-timeout-required
tb.rulenode.connect-timeout-range
tb.rulenode.connect-timeout-range
{{ \'tb.rulenode.clean-session\' | translate }} {{ \'tb.rulenode.enable-ssl\' | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{credentialsValue.name | translate}}
tb.rulenode.credentials-type-required
tb.rulenode.username-required
tb.rulenode.password-required
'},function(e,t){e.exports="
tb.rulenode.interval-seconds-required
tb.rulenode.min-interval-seconds-message
tb.rulenode.output-timeseries-key-prefix-required
"},function(e,t){e.exports="
tb.rulenode.period-seconds-required
tb.rulenode.min-period-0-seconds-message
tb.rulenode.max-pending-messages-required
tb.rulenode.max-pending-messages-range
tb.rulenode.max-pending-messages-range
"},function(e,t){e.exports='
{{ property }}
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
{{ \'tb.rulenode.automatic-recovery\' | translate }}
tb.rulenode.min-connection-timeout-ms-message
tb.rulenode.min-handshake-timeout-ms-message
'},function(e,t){e.exports='
tb.rulenode.endpoint-url-pattern-required
tb.rulenode.endpoint-url-pattern-hint
{{ type }}
tb.rulenode.headers-hint
'},function(e,t){e.exports="
"},function(e,t){e.exports="
tb.rulenode.timeout-required
tb.rulenode.min-timeout-message
"},function(e,t){e.exports='
{{ \'tb.rulenode.use-system-smtp-settings\' | translate }}
{{smtpProtocol.toUpperCase()}}
tb.rulenode.smtp-host-required
tb.rulenode.smtp-port-required
tb.rulenode.smtp-port-range
tb.rulenode.smtp-port-range
tb.rulenode.timeout-required
tb.rulenode.min-timeout-msec-message
{{ \'tb.rulenode.enable-tls\' | translate }}
'},function(e,t){e.exports="
tb.rulenode.topic-arn-pattern-required
tb.rulenode.topic-arn-pattern-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
"},function(e,t){e.exports='
{{ type.name | translate }}
tb.rulenode.queue-url-pattern-required
tb.rulenode.queue-url-pattern-hint
tb.rulenode.min-delay-seconds-message
tb.rulenode.max-delay-seconds-message
tb.rulenode.message-attributes-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
'; -},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{ (\'relation.search-direction.\' + direction) | translate}}
relation.relation-type
device.device-types
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports='
{{ type }}
tb.rulenode.start-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.end-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
'},function(e,t){e.exports='
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},26,function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
"},function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.from-template-required
tb.rulenode.from-template-hint
tb.rulenode.to-template-required
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.subject-template-required
tb.rulenode.subject-template-hint
tb.rulenode.body-template-required
tb.rulenode.body-template-hint
"},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(6),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(7),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n,r){var a=function(a,i,l,s){var u=o.default;i.html(u),a.types=n,a.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(a.configuration)}),s.$render=function(){a.configuration=s.$viewValue},a.testDetailsBuildJs=function(e){var n=angular.copy(a.configuration.alarmDetailsBuildJs);r.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],a.ruleNodeId).then(function(e){a.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(i.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:a}}a.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(8),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n,r){var a=function(a,i,l,s){var u=o.default;i.html(u),a.types=n,a.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(a.configuration)}),s.$render=function(){a.configuration=s.$viewValue},a.testDetailsBuildJs=function(e){var n=angular.copy(a.configuration.alarmDetailsBuildJs);r.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],a.ruleNodeId).then(function(e){a.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(i.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:a}}a.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(9),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n,r){var a=function(a,i,l,s){var u=o.default;i.html(u),a.types=n,a.originator=null,a.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(a.configuration)}),s.$render=function(){a.configuration=s.$viewValue,a.configuration.originatorId&&a.configuration.originatorType?a.originator={id:a.configuration.originatorId,entityType:a.configuration.originatorType}:a.originator=null,a.$watch("originator",function(e,t){angular.equals(e,t)||(a.originator?(s.$viewValue.originatorId=a.originator.id,s.$viewValue.originatorType=a.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},a.testScript=function(e){var n=angular.copy(a.configuration.jsScript);r.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],a.ruleNodeId).then(function(e){a.configuration.jsScript=e,s.$setDirty()})},e(i.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:a}}a.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a,n(1);var i=n(10),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(61),i=r(a),o=n(44),l=r(o),s=n(47),u=r(s),d=n(46),c=r(d),m=n(45),g=r(m),p=n(50),f=r(p),b=n(56),v=r(b),y=n(57),q=r(y),h=n(55),$=r(h),T=n(49),k=r(T),x=n(59),w=r(x),C=n(60),M=r(C),_=n(54),S=r(_),N=n(51),V=r(N),E=n(58),P=r(E),F=n(53),j=r(F),A=n(52),O=r(A),I=n(43),K=r(I),D=n(62),R=r(D);t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTimeseriesConfig",i.default).directive("tbActionNodeAttributesConfig",l.default).directive("tbActionNodeGeneratorConfig",u.default).directive("tbActionNodeCreateAlarmConfig",c.default).directive("tbActionNodeClearAlarmConfig",g.default).directive("tbActionNodeLogConfig",f.default).directive("tbActionNodeRpcReplyConfig",v.default).directive("tbActionNodeRpcRequestConfig",q.default).directive("tbActionNodeRestApiCallConfig",$.default).directive("tbActionNodeKafkaConfig",k.default).directive("tbActionNodeSnsConfig",w.default).directive("tbActionNodeSqsConfig",M.default).directive("tbActionNodeRabbitMqConfig",S.default).directive("tbActionNodeMqttConfig",V.default).directive("tbActionNodeSendEmailConfig",P.default).directive("tbActionNodeMsgDelayConfig",j.default).directive("tbActionNodeMsgCountConfig",O.default).directive("tbActionNodeAssignToCustomerConfig",K.default).directive("tbActionNodeUnAssignToCustomerConfig",R.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.ackValues=["all","-1","0","1"],t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(11),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){var s=o.default;a.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var a=angular.copy(r.configuration.jsScript);n.testNodeScript(e,a,"string",t.instant("tb.rulenode.to-string")+"","ToString",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}a.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(12),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){var s=o.default;a.html(s),r.$mdExpansionPanel=t,r.ruleNodeTypes=n,r.credentialsTypeChanged=function(){var e=r.configuration.credentials.type;r.configuration.credentials={},r.configuration.credentials.type=e,r.updateValidity()},r.certFileAdded=function(e,t){var n=new FileReader;n.onload=function(n){r.$apply(function(){if(n.target.result){l.$setDirty();var a=n.target.result;a&&a.length>0&&("caCert"==t&&(r.configuration.credentials.caCertFileName=e.name,r.configuration.credentials.caCert=a),"privateKey"==t&&(r.configuration.credentials.privateKeyFileName=e.name,r.configuration.credentials.privateKey=a),"Cert"==t&&(r.configuration.credentials.certFileName=e.name,r.configuration.credentials.cert=a)),r.updateValidity()}})},n.readAsText(e.file)},r.clearCertFile=function(e){l.$setDirty(),"caCert"==e&&(r.configuration.credentials.caCertFileName=null,r.configuration.credentials.caCert=null),"privateKey"==e&&(r.configuration.credentials.privateKeyFileName=null,r.configuration.credentials.privateKey=null),"Cert"==e&&(r.configuration.credentials.certFileName=null,r.configuration.credentials.cert=null),r.updateValidity()},r.updateValidity=function(){var e=!0,t=r.configuration.credentials;t.type==n.mqttCredentialTypes["cert.PEM"].value&&(t.caCert&&t.cert&&t.privateKey||(e=!1)),l.$setValidity("Certs",e)},r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:r}}a.$inject=["$compile","$mdExpansionPanel","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a,n(2);var i=n(13),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(14),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(15),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"],t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(16),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(17),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(18),o=r(i)},function(e,t,n){"use strict"; -function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(19),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.smtpProtocols=["smtp","smtps"],t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(20),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(21),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:n}}a.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(22),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(23),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(24),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(25),o=r(i)},function(e,t){"use strict";function n(e){var t=function(t,n,r,a){n.html("
"),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(26),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(27),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){var s=o.default;a.html(s);var u=186;r.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,u],r.ruleNodeTypes=n,r.aggPeriodTimeUnits={},r.aggPeriodTimeUnits.MINUTES=n.timeUnit.MINUTES,r.aggPeriodTimeUnits.HOURS=n.timeUnit.HOURS,r.aggPeriodTimeUnits.DAYS=n.timeUnit.DAYS,r.aggPeriodTimeUnits.MILLISECONDS=n.timeUnit.MILLISECONDS,r.aggPeriodTimeUnits.SECONDS=n.timeUnit.SECONDS,r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{},link:r}}a.$inject=["$compile","$mdConstant","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(28),o=r(i);n(3)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(69),i=r(a),o=n(70),l=r(o),s=n(66),u=r(s),d=n(71),c=r(d),m=n(65),g=r(m),p=n(72),f=r(p),b=n(67),v=r(b);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",i.default).directive("tbEnrichmentNodeOriginatorFieldsConfig",l.default).directive("tbEnrichmentNodeDeviceAttributesConfig",u.default).directive("tbEnrichmentNodeRelatedAttributesConfig",c.default).directive("tbEnrichmentNodeCustomerAttributesConfig",g.default).directive("tbEnrichmentNodeTenantAttributesConfig",f.default).directive("tbEnrichmentNodeGetTelemetryFromDatabase",v.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(29),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(30),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(31),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(32),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(33),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(77),i=r(a),o=n(75),l=r(o),s=n(78),u=r(s),d=n(73),c=r(d),m=n(76),g=r(m);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",i.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).directive("tbFilterNodeCheckRelationConfig",c.default).directive("tbFilterNodeOriginatorTypeConfig",g.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),a.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),a.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=a,t.removeKeyVal=i,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||a.$setViewValue(t.query)}),a.$render=function(){if(a.$viewValue){var e=a.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(38),o=r(i);n(5)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(39),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t){var n=function(n,r,a,i){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}a.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(40),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(81),i=r(a),o=n(83),l=r(o),s=n(84),u=r(s);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",i.default).directive("tbTransformationNodeScriptConfig",l.default).directive("tbTransformationNodeToEmailConfig",u.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e,t,n){var r=function(r,a,i,l){var s=o.default;a.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var a=angular.copy(r.configuration.jsScript);n.testNodeScript(e,a,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}a.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(41),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){var t=function(t,n,r,a){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||a.$setViewValue(t.configuration)}),a.$render=function(){t.configuration=a.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}a.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(42),o=r(i)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var a=n(88),i=r(a),o=n(74),l=r(o),s=n(68),u=r(s),d=n(82),c=r(d),m=n(48),g=r(m),p=n(64),f=r(p),b=n(80),v=r(b),y=n(63),q=r(y),h=n(79),$=r(h),T=n(87),k=r(T);t.default=angular.module("thingsboard.ruleChain.config",[i.default,l.default,u.default,c.default,g.default]).directive("tbNodeEmptyConfig",f.default).directive("tbRelationsQueryConfig",v.default).directive("tbDeviceRelationsQueryConfig",q.default).directive("tbKvMapConfig",$.default).config(k.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{"customer-name-pattern":"Customer name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","customer-cache-expiration":"Customers cache expiration time (sec)","customer-name-pattern-hint":"Customer name pattern, use ${metaKeyName} to substitute variables from metadata","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","start-interval":"Start Interval","end-interval":"End Interval","start-interval-time-unit":"Start Interval Time Unit","end-interval-time-unit":"End Interval Time Unit","fetch-mode":"Fetch mode","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Time value should be in a range from 1 to 2147483647'.","start-interval-value-required":"Start interval value is required.","end-interval-value-required":"End interval value is required.",filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","fields-mapping":"Fields mapping","fields-mapping-required":"At least one field mapping should be specified.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","from-template-hint":"From address template, use ${metaKeyName} to substitute variables from metadata","to-template":"To Template","to-template-required":"To Template is required","mail-address-list-template-hint":"Comma separated address list, use ${metaKeyName} to substitute variables from metadata","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","subject-template-hint":"Mail subject template, use ${metaKeyName} to substitute variables from metadata","body-template":"Body Template","body-template-required":"Body Template is required","body-template-hint":"Mail body template, use ${metaKeyName} to substitute variables from metadata","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","endpoint-url-pattern-hint":"HTTP URL address pattern, use ${metaKeyName} to substitute variables from metadata","request-method":"Request method",headers:"Headers","headers-hint":"Use ${metaKeyName} in header/value fields to substitute variables from metadata",header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","topic-pattern-required":"Topic pattern is required","mqtt-topic-pattern-hint":"MQTT topic pattern, use ${metaKeyName} to substitute variables from metadata","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","topic-arn-pattern-hint":"Topic ARN pattern, use ${metaKeyName} to substitute variables from metadata","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","queue-url-pattern-hint":"Queue URL pattern, use ${metaKeyName} to substitute variables from metadata","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","message-attributes":"Message attributes","message-attributes-hint":"Use ${metaKeyName} in name/value fields to substitute variables from metadata","connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"CA certificate file *","private-key":"Private key file *",cert:"Certificate file *","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required."},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};e.translations("en_US",t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function a(e){(0,o.default)(e)}a.$inject=["$translateProvider"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=a;var i=n(86),o=r(i)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}},fetchModeType:["FIRST","LAST","ALL"],httpRequestType:["GET","POST","PUT","DELETE"],sqsQueueType:{STANDARD:{name:"tb.rulenode.sqs-queue-standard",value:"STANDARD"},FIFO:{name:"tb.rulenode.sqs-queue-fifo",value:"FIFO"}},timeUnit:{MILLISECONDS:{value:"MILLISECONDS",name:"tb.rulenode.time-unit-milliseconds"},SECONDS:{value:"SECONDS",name:"tb.rulenode.time-unit-seconds"},MINUTES:{value:"MINUTES",name:"tb.rulenode.time-unit-minutes"},HOURS:{value:"HOURS",name:"tb.rulenode.time-unit-hours"},DAYS:{value:"DAYS",name:"tb.rulenode.time-unit-days"}},mqttCredentialTypes:{anonymous:{value:"anonymous",name:"tb.rulenode.credentials-anonymous"},basic:{value:"basic",name:"tb.rulenode.credentials-basic"},"cert.PEM":{value:"cert.PEM",name:"tb.rulenode.credentials-pem"}}}).name}])); +!function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),i=e[t[0]];return function(e,t,r){i.apply(this,[e,t,r].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(89)},function(e,t){},1,1,1,1,function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
{{ 'tb.rulenode.create-customer-if-not-exists' | translate }}
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{scope.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
{{ severity.name | translate}}
tb.rulenode.alarm-severity-required
{{ 'tb.rulenode.propagate' | translate }}
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-type-pattern-required
tb.rulenode.entity-type-pattern-hint
{{ 'tb.rulenode.create-entity-if-not-exists' | translate }}
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.bootstrap-servers-required
tb.rulenode.min-retries-message
tb.rulenode.min-batch-size-bytes-message
tb.rulenode.min-linger-ms-message
tb.rulenode.min-buffer-memory-bytes-message
{{ ackValue }}
tb.rulenode.key-serializer-required
tb.rulenode.value-serializer-required
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-to-string-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.mqtt-topic-pattern-hint
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
tb.rulenode.connect-timeout-required
tb.rulenode.connect-timeout-range
tb.rulenode.connect-timeout-range
{{ \'tb.rulenode.clean-session\' | translate }} {{ \'tb.rulenode.enable-ssl\' | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{credentialsValue.name | translate}}
tb.rulenode.credentials-type-required
tb.rulenode.username-required
tb.rulenode.password-required
'},function(e,t){e.exports="
tb.rulenode.interval-seconds-required
tb.rulenode.min-interval-seconds-message
tb.rulenode.output-timeseries-key-prefix-required
"},function(e,t){e.exports="
tb.rulenode.period-seconds-required
tb.rulenode.min-period-0-seconds-message
tb.rulenode.max-pending-messages-required
tb.rulenode.max-pending-messages-range
tb.rulenode.max-pending-messages-range
"},function(e,t){e.exports='
{{ property }}
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
{{ \'tb.rulenode.automatic-recovery\' | translate }}
tb.rulenode.min-connection-timeout-ms-message
tb.rulenode.min-handshake-timeout-ms-message
'},function(e,t){e.exports='
tb.rulenode.endpoint-url-pattern-required
tb.rulenode.endpoint-url-pattern-hint
{{ type }}
tb.rulenode.headers-hint
'},function(e,t){e.exports="
"},function(e,t){e.exports="
tb.rulenode.timeout-required
tb.rulenode.min-timeout-message
"},function(e,t){e.exports='
{{ \'tb.rulenode.use-system-smtp-settings\' | translate }}
{{smtpProtocol.toUpperCase()}}
tb.rulenode.smtp-host-required
tb.rulenode.smtp-port-required
tb.rulenode.smtp-port-range
tb.rulenode.smtp-port-range
tb.rulenode.timeout-required
tb.rulenode.min-timeout-msec-message
{{ \'tb.rulenode.enable-tls\' | translate }}
'; +},function(e,t){e.exports="
tb.rulenode.topic-arn-pattern-required
tb.rulenode.topic-arn-pattern-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
"},function(e,t){e.exports='
{{ type.name | translate }}
tb.rulenode.queue-url-pattern-required
tb.rulenode.queue-url-pattern-hint
tb.rulenode.min-delay-seconds-message
tb.rulenode.max-delay-seconds-message
tb.rulenode.message-attributes-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
'},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{ (\'relation.search-direction.\' + direction) | translate}}
relation.relation-type
device.device-types
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports='
{{ type }}
tb.rulenode.start-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.end-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
'},function(e,t){e.exports='
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},28,function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
"},function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.from-template-required
tb.rulenode.from-template-hint
tb.rulenode.to-template-required
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.subject-template-required
tb.rulenode.subject-template-hint
tb.rulenode.body-template-required
tb.rulenode.body-template-hint
"},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(6),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(7),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,i){var r=function(r,a,l,s){var u=o.default;a.html(u),r.types=n,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue},r.testDetailsBuildJs=function(e){var n=angular.copy(r.configuration.alarmDetailsBuildJs);i.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(8),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,i){var r=function(r,a,l,s){var u=o.default;a.html(u),r.types=n,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue},r.testDetailsBuildJs=function(e){var n=angular.copy(r.configuration.alarmDetailsBuildJs);i.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(9),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(10),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(11),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,i){var r=function(r,a,l,s){var u=o.default;a.html(u),r.types=n,r.originator=null,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue,r.configuration.originatorId&&r.configuration.originatorType?r.originator={id:r.configuration.originatorId,entityType:r.configuration.originatorType}:r.originator=null,r.$watch("originator",function(e,t){angular.equals(e,t)||(r.originator?(s.$viewValue.originatorId=r.originator.id,s.$viewValue.originatorType=r.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},r.testScript=function(e){var n=angular.copy(r.configuration.jsScript);i.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,s.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r,n(1);var a=n(12),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(65),a=i(r),o=n(46),l=i(o),s=n(51),u=i(s),d=n(48),c=i(d),m=n(47),g=i(m),p=n(54),f=i(p),b=n(60),v=i(b),y=n(61),q=i(y),h=n(59),$=i(h),x=n(53),T=i(x),k=n(63),C=i(k),w=n(64),M=i(w),_=n(58),S=i(_),N=n(55),E=i(N),V=n(62),P=i(V),F=n(57),j=i(F),A=n(56),O=i(A),I=n(45),R=i(I),K=n(66),D=i(K),U=n(50),L=i(U),z=n(49),B=i(z);t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTimeseriesConfig",a.default).directive("tbActionNodeAttributesConfig",l.default).directive("tbActionNodeGeneratorConfig",u.default).directive("tbActionNodeCreateAlarmConfig",c.default).directive("tbActionNodeClearAlarmConfig",g.default).directive("tbActionNodeLogConfig",f.default).directive("tbActionNodeRpcReplyConfig",v.default).directive("tbActionNodeRpcRequestConfig",q.default).directive("tbActionNodeRestApiCallConfig",$.default).directive("tbActionNodeKafkaConfig",T.default).directive("tbActionNodeSnsConfig",C.default).directive("tbActionNodeSqsConfig",M.default).directive("tbActionNodeRabbitMqConfig",S.default).directive("tbActionNodeMqttConfig",E.default).directive("tbActionNodeSendEmailConfig",P.default).directive("tbActionNodeMsgDelayConfig",j.default).directive("tbActionNodeMsgCountConfig",O.default).directive("tbActionNodeAssignToCustomerConfig",R.default).directive("tbActionNodeUnAssignToCustomerConfig",D.default).directive("tbActionNodeDeleteRelationConfig",L.default).directive("tbActionNodeCreateRelationConfig",B.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.ackValues=["all","-1","0","1"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel", +scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(13),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s),i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},i.testScript=function(e){var r=angular.copy(i.configuration.jsScript);n.testNodeScript(e,r,"string",t.instant("tb.rulenode.to-string")+"","ToString",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.jsScript=e,l.$setDirty()})},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}r.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(14),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s),i.$mdExpansionPanel=t,i.ruleNodeTypes=n,i.credentialsTypeChanged=function(){var e=i.configuration.credentials.type;i.configuration.credentials={},i.configuration.credentials.type=e,i.updateValidity()},i.certFileAdded=function(e,t){var n=new FileReader;n.onload=function(n){i.$apply(function(){if(n.target.result){l.$setDirty();var r=n.target.result;r&&r.length>0&&("caCert"==t&&(i.configuration.credentials.caCertFileName=e.name,i.configuration.credentials.caCert=r),"privateKey"==t&&(i.configuration.credentials.privateKeyFileName=e.name,i.configuration.credentials.privateKey=r),"Cert"==t&&(i.configuration.credentials.certFileName=e.name,i.configuration.credentials.cert=r)),i.updateValidity()}})},n.readAsText(e.file)},i.clearCertFile=function(e){l.$setDirty(),"caCert"==e&&(i.configuration.credentials.caCertFileName=null,i.configuration.credentials.caCert=null),"privateKey"==e&&(i.configuration.credentials.privateKeyFileName=null,i.configuration.credentials.privateKey=null),"Cert"==e&&(i.configuration.credentials.certFileName=null,i.configuration.credentials.cert=null),i.updateValidity()},i.updateValidity=function(){var e=!0,t=i.configuration.credentials;t.type==n.mqttCredentialTypes["cert.PEM"].value&&(t.caCert&&t.cert&&t.privateKey||(e=!1)),l.$setValidity("Certs",e)},i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:i}}r.$inject=["$compile","$mdExpansionPanel","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r,n(2);var a=n(15),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(16),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(17),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(18),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(19),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(20),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(21),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.smtpProtocols=["smtp","smtps"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(22),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(23),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(24),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(25),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(26),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(27),o=i(a)},function(e,t){"use strict";function n(e){var t=function(t,n,i,r){n.html("
"),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(28),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(29),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s);var u=186;i.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,u],i.ruleNodeTypes=n,i.aggPeriodTimeUnits={},i.aggPeriodTimeUnits.MINUTES=n.timeUnit.MINUTES,i.aggPeriodTimeUnits.HOURS=n.timeUnit.HOURS,i.aggPeriodTimeUnits.DAYS=n.timeUnit.DAYS,i.aggPeriodTimeUnits.MILLISECONDS=n.timeUnit.MILLISECONDS,i.aggPeriodTimeUnits.SECONDS=n.timeUnit.SECONDS,i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{},link:i}}r.$inject=["$compile","$mdConstant","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(30),o=i(a);n(3)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(73),a=i(r),o=n(74),l=i(o),s=n(70),u=i(s),d=n(75),c=i(d),m=n(69),g=i(m),p=n(76),f=i(p),b=n(71),v=i(b);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",a.default).directive("tbEnrichmentNodeOriginatorFieldsConfig",l.default).directive("tbEnrichmentNodeDeviceAttributesConfig",u.default).directive("tbEnrichmentNodeRelatedAttributesConfig",c.default).directive("tbEnrichmentNodeCustomerAttributesConfig",g.default).directive("tbEnrichmentNodeTenantAttributesConfig",f.default).directive("tbEnrichmentNodeGetTelemetryFromDatabase",v.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(31),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(32),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(33),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(34),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(35),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(81),a=i(r),o=n(79),l=i(o),s=n(82),u=i(s),d=n(77),c=i(d),m=n(80),g=i(m);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",a.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).directive("tbFilterNodeCheckRelationConfig",c.default).directive("tbFilterNodeOriginatorTypeConfig",g.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),r.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),r.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=r,t.removeKeyVal=a,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||r.$setViewValue(t.query)}),r.$render=function(){if(r.$viewValue){var e=r.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(40),o=i(a);n(5)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(41),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(42),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(85),a=i(r),o=n(87),l=i(o),s=n(88),u=i(s);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",a.default).directive("tbTransformationNodeScriptConfig",l.default).directive("tbTransformationNodeToEmailConfig",u.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s),i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},i.testScript=function(e){var r=angular.copy(i.configuration.jsScript);n.testNodeScript(e,r,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.jsScript=e,l.$setDirty()})},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}r.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(43),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(44),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(92),a=i(r),o=n(78),l=i(o),s=n(72),u=i(s),d=n(86),c=i(d),m=n(52),g=i(m),p=n(68),f=i(p),b=n(84),v=i(b),y=n(67),q=i(y),h=n(83),$=i(h),x=n(91),T=i(x);t.default=angular.module("thingsboard.ruleChain.config",[a.default,l.default,u.default,c.default,g.default]).directive("tbNodeEmptyConfig",f.default).directive("tbRelationsQueryConfig",v.default).directive("tbDeviceRelationsQueryConfig",q.default).directive("tbKvMapConfig",$.default).config(T.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{"create-entity-if-not-exists":"Create new entity if not exists","entity-name-pattern":"Name pattern","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern, use ${metaKeyName} to substitute variables from metadata","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","entity-type-pattern-hint":"Type pattern, use ${metaKeyName} to substitute variables from metadata","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","customer-cache-expiration":"Customers cache expiration time (sec)","customer-name-pattern-hint":"Customer name pattern, use ${metaKeyName} to substitute variables from metadata","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","start-interval":"Start Interval","end-interval":"End Interval","start-interval-time-unit":"Start Interval Time Unit","end-interval-time-unit":"End Interval Time Unit","fetch-mode":"Fetch mode","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Time value should be in a range from 1 to 2147483647'.","start-interval-value-required":"Start interval value is required.","end-interval-value-required":"End interval value is required.",filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","fields-mapping":"Fields mapping","fields-mapping-required":"At least one field mapping should be specified.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","from-template-hint":"From address template, use ${metaKeyName} to substitute variables from metadata","to-template":"To Template","to-template-required":"To Template is required","mail-address-list-template-hint":"Comma separated address list, use ${metaKeyName} to substitute variables from metadata","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","subject-template-hint":"Mail subject template, use ${metaKeyName} to substitute variables from metadata","body-template":"Body Template","body-template-required":"Body Template is required","body-template-hint":"Mail body template, use ${metaKeyName} to substitute variables from metadata","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","endpoint-url-pattern-hint":"HTTP URL address pattern, use ${metaKeyName} to substitute variables from metadata","request-method":"Request method",headers:"Headers","headers-hint":"Use ${metaKeyName} in header/value fields to substitute variables from metadata",header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","topic-pattern-required":"Topic pattern is required","mqtt-topic-pattern-hint":"MQTT topic pattern, use ${metaKeyName} to substitute variables from metadata","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","topic-arn-pattern-hint":"Topic ARN pattern, use ${metaKeyName} to substitute variables from metadata","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern", +"queue-url-pattern-required":"Queue URL pattern is required","queue-url-pattern-hint":"Queue URL pattern, use ${metaKeyName} to substitute variables from metadata","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","message-attributes":"Message attributes","message-attributes-hint":"Use ${metaKeyName} in name/value fields to substitute variables from metadata","connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"CA certificate file *","private-key":"Private key file *",cert:"Certificate file *","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required."},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};e.translations("en_US",t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){(0,o.default)(e)}r.$inject=["$translateProvider"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(90),o=i(a)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}},fetchModeType:["FIRST","LAST","ALL"],httpRequestType:["GET","POST","PUT","DELETE"],sqsQueueType:{STANDARD:{name:"tb.rulenode.sqs-queue-standard",value:"STANDARD"},FIFO:{name:"tb.rulenode.sqs-queue-fifo",value:"FIFO"}},timeUnit:{MILLISECONDS:{value:"MILLISECONDS",name:"tb.rulenode.time-unit-milliseconds"},SECONDS:{value:"SECONDS",name:"tb.rulenode.time-unit-seconds"},MINUTES:{value:"MINUTES",name:"tb.rulenode.time-unit-minutes"},HOURS:{value:"HOURS",name:"tb.rulenode.time-unit-hours"},DAYS:{value:"DAYS",name:"tb.rulenode.time-unit-days"}},mqttCredentialTypes:{anonymous:{value:"anonymous",name:"tb.rulenode.credentials-anonymous"},basic:{value:"basic",name:"tb.rulenode.credentials-basic"},"cert.PEM":{value:"cert.PEM",name:"tb.rulenode.credentials-pem"}}}).name}])); //# sourceMappingURL=rulenode-core-config.js.map \ No newline at end of file From ab58776f04f9b115cc5b148c77746c59e2348cf1 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Wed, 12 Dec 2018 20:02:39 +0200 Subject: [PATCH 02/27] getAttributes black-box-test --- .../device/DeviceActorMessageProcessor.java | 4 +- .../server/msa/AbstractContainerTest.java | 9 ++- .../msa/connectivity/HttpClientTest.java | 59 ++++++++++++++++++- tools/pom.xml | 1 - .../thingsboard/client/tools/RestClient.java | 41 +++++++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index e46a95972f..50a4f7d01b 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -16,7 +16,6 @@ package org.thingsboard.server.actors.device; import akka.actor.ActorContext; -import akka.event.LoggingAdapter; import com.datastax.driver.core.utils.UUIDs; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; @@ -42,7 +41,6 @@ import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; -import org.thingsboard.server.common.msg.cluster.ClusterEventMsg; import org.thingsboard.server.common.msg.rpc.ToDeviceRpcRequest; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.msg.timeout.DeviceActorClientSideRpcTimeoutMsg; @@ -295,7 +293,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { return systemContext.getAttributesService().findAll(tenantId, deviceId, scope); } } else { - return Futures.immediateFuture(Collections.emptyList()); + return systemContext.getAttributesService().findAll(tenantId, deviceId, scope); } } diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java index 4c3ac8362c..bbabc2eb88 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/AbstractContainerTest.java @@ -32,7 +32,8 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.SSLContexts; -import org.junit.*; +import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; import org.junit.runner.Description; @@ -43,7 +44,10 @@ import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.msa.mapper.WsTelemetryResponse; -import javax.net.ssl.*; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; import java.net.URI; import java.security.cert.X509Certificate; import java.util.List; @@ -54,6 +58,7 @@ import java.util.Random; public abstract class AbstractContainerTest { protected static final String HTTPS_URL = "https://localhost"; protected static final String WSS_URL = "wss://localhost"; + protected static String TB_TOKEN; protected static RestClient restClient; protected ObjectMapper mapper = new ObjectMapper(); diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java index a6e89de185..a5796cc69a 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.msa.connectivity; +import com.fasterxml.jackson.databind.JsonNode; import com.google.common.collect.Sets; import org.junit.Assert; import org.junit.Test; @@ -25,6 +26,15 @@ import org.thingsboard.server.msa.AbstractContainerTest; import org.thingsboard.server.msa.WsClient; import org.thingsboard.server.msa.mapper.WsTelemetryResponse; + +import java.util.Optional; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.thingsboard.server.common.data.DataConstants.DEVICE; +import static org.thingsboard.server.common.data.DataConstants.SHARED_SCOPE; + public class HttpClientTest extends AbstractContainerTest { @Test @@ -52,6 +62,53 @@ public class HttpClientTest extends AbstractContainerTest { Assert.assertTrue(verify(actualLatestTelemetry, "doubleKey", Double.toString(42.0))); Assert.assertTrue(verify(actualLatestTelemetry, "longKey", Long.toString(73))); - restClient.getRestTemplate().delete(HTTPS_URL + "/api/device/" + device.getId()); + restClient.deleteDevice(device.getId()); + } + + @Test + public void getAttributes() throws Exception { + restClient.login("tenant@thingsboard.org", "tenant"); + TB_TOKEN = restClient.getToken(); + + Device device = createDevice("test"); + String accessToken = restClient.getCredentials(device.getId()).getCredentialsId(); + assertNotNull(accessToken); + + ResponseEntity deviceSharedAttributes = restClient.getRestTemplate() + .postForEntity(HTTPS_URL + "/api/plugins/telemetry/" + DEVICE + "/" + device.getId().toString() + "/attributes/" + SHARED_SCOPE, mapper.readTree(createPayload().toString()), + ResponseEntity.class, + accessToken); + + ResponseEntity deviceClientsAttributes = restClient.getRestTemplate() + .postForEntity(HTTPS_URL + "/api/v1/" + accessToken + "/attributes/", mapper.readTree(createPayload().toString()), + ResponseEntity.class, + accessToken); + + Assert.assertTrue(deviceSharedAttributes.getStatusCode().is2xxSuccessful()); + Assert.assertTrue(deviceClientsAttributes.getStatusCode().is2xxSuccessful()); + + Optional allOptional = restClient.getAttributes(accessToken, null, null); + assertTrue(allOptional.isPresent()); + + JsonNode all = allOptional.get(); + assertEquals(all.get("shared"), mapper.readTree(createPayload().toString())); + assertEquals(all.get("client"), mapper.readTree(createPayload().toString())); + + Optional sharedOptional = restClient.getAttributes(accessToken, null, "stringKey"); + assertTrue(sharedOptional.isPresent()); + + JsonNode shared = sharedOptional.get(); + assertEquals(shared.get("shared").get("stringKey"), mapper.readTree(createPayload().get("stringKey").toString())); + assertEquals(shared.get("client"), mapper.readTree(createPayload().toString())); + + Optional clientOptional = restClient.getAttributes(accessToken, "longKey,stringKey", null); + assertTrue(clientOptional.isPresent()); + + JsonNode client = clientOptional.get(); + assertEquals(client.get("shared"), mapper.readTree(createPayload().toString())); + assertEquals(client.get("client").get("longKey"), mapper.readTree(createPayload().get("longKey").toString())); + assertEquals(client.get("client").get("stringKey"), mapper.readTree(createPayload().get("stringKey").toString())); + + restClient.deleteDevice(device.getId()); } } diff --git a/tools/pom.xml b/tools/pom.xml index c1c1ded1d7..616d894a79 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -23,7 +23,6 @@ 2.2.1-SNAPSHOT thingsboard - org.thingsboard tools jar diff --git a/tools/src/main/java/org/thingsboard/client/tools/RestClient.java b/tools/src/main/java/org/thingsboard/client/tools/RestClient.java index 4c8c0a4f37..90bfc01dec 100644 --- a/tools/src/main/java/org/thingsboard/client/tools/RestClient.java +++ b/tools/src/main/java/org/thingsboard/client/tools/RestClient.java @@ -107,6 +107,27 @@ public class RestClient implements ClientHttpRequestInterceptor { } } + public Optional getAttributes(String accessToken, String clientKeys, String sharedKeys) { + Map params = new HashMap<>(); + params.put("accessToken", accessToken); + params.put("clientKeys", clientKeys); + params.put("sharedKeys", sharedKeys); + try { + ResponseEntity telemetryEntity = restTemplate.getForEntity(baseURL + "/api/v1/{accessToken}/attributes?clientKeys={clientKeys}&sharedKeys={sharedKeys}", JsonNode.class, params); + return Optional.of(telemetryEntity.getBody()); + } catch (HttpClientErrorException exception) { + if (exception.getStatusCode() == HttpStatus.NOT_FOUND) { + return Optional.empty(); + } else { + throw exception; + } + } + } + + public Customer createCustomer(Customer customer) { + return restTemplate.postForEntity(baseURL + "/api/customer", customer, Customer.class).getBody(); + } + public Customer createCustomer(String title) { Customer customer = new Customer(); customer.setTitle(title); @@ -120,6 +141,14 @@ public class RestClient implements ClientHttpRequestInterceptor { return restTemplate.postForEntity(baseURL + "/api/device", device, Device.class).getBody(); } + public Device createDevice(Device device) { + return restTemplate.postForEntity(baseURL + "/api/device", device, Device.class).getBody(); + } + + public Asset createAsset(Asset asset) { + return restTemplate.postForEntity(baseURL + "/api/asset", asset, Asset.class).getBody(); + } + public Asset createAsset(String name, String type) { Asset asset = new Asset(); asset.setName(name); @@ -131,6 +160,18 @@ public class RestClient implements ClientHttpRequestInterceptor { return restTemplate.postForEntity(baseURL + "/api/alarm", alarm, Alarm.class).getBody(); } + public void deleteCustomer(CustomerId customerId) { + restTemplate.delete(baseURL + "/api/customer/{customerId}", customerId); + } + + public void deleteDevice(DeviceId deviceId) { + restTemplate.delete(baseURL + "/api/device/{deviceId}", deviceId); + } + + public void deleteAsset(AssetId assetId) { + restTemplate.delete(baseURL + "/api/asset/{assetId}", assetId); + } + public Device assignDevice(CustomerId customerId, DeviceId deviceId) { return restTemplate.postForEntity(baseURL + "/api/customer/{customerId}/device/{deviceId}", null, Device.class, customerId.toString(), deviceId.toString()).getBody(); From 50f964e17a28f77eac1b735963b111f58e06b751 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Fri, 14 Dec 2018 18:02:20 +0200 Subject: [PATCH 03/27] refactoring getAttributesKvEntries method --- .../device/DeviceActorMessageProcessor.java | 84 ++++++++++++++++--- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index 50a4f7d01b..6f66a77eb2 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -30,7 +30,6 @@ import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.actors.shared.AbstractContextAwareMsgProcessor; -import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; @@ -85,6 +84,9 @@ import java.util.UUID; import java.util.function.Consumer; import java.util.stream.Collectors; +import static org.thingsboard.server.common.data.DataConstants.CLIENT_SCOPE; +import static org.thingsboard.server.common.data.DataConstants.SHARED_SCOPE; + /** * @author Andrew Shvayka */ @@ -261,10 +263,8 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { } private void handleGetAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, GetAttributeRequestMsg request) { - ListenableFuture> clientAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.CLIENT_SCOPE, toOptionalSet(request.getClientAttributeNamesList())); - ListenableFuture> sharedAttributesFuture = getAttributeKvEntries(deviceId, DataConstants.SHARED_SCOPE, toOptionalSet(request.getSharedAttributeNamesList())); int requestId = request.getRequestId(); - Futures.addCallback(Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)), new FutureCallback>>() { + Futures.addCallback(getAttributesKvEntries(request), new FutureCallback>>() { @Override public void onSuccess(@Nullable List> result) { GetAttributeResponseMsg responseMsg = GetAttributeResponseMsg.newBuilder() @@ -285,16 +285,76 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { }); } - private ListenableFuture> getAttributeKvEntries(DeviceId deviceId, String scope, Optional> names) { - if (names.isPresent()) { - if (!names.get().isEmpty()) { - return systemContext.getAttributesService().find(tenantId, deviceId, scope, names.get()); + private ListenableFuture>> getAttributesKvEntries(GetAttributeRequestMsg request) { + ListenableFuture> clientAttributesFuture; + ListenableFuture> sharedAttributesFuture; + if (!clientIsPresent(request) && !sharedIsPresent(request)) { + clientAttributesFuture = findAllClientAttributes(); + sharedAttributesFuture = findAllSharedAttributes(); + } else if (clientIsPresent(request) && sharedIsPresent(request)) { + if (clientIsNotEmpty(request) && sharedIsNotEmpty(request)) { + clientAttributesFuture = findClientAttributes(request); + sharedAttributesFuture = findSharedAttributes(request); + } else { + clientAttributesFuture = findAllClientAttributes(); + sharedAttributesFuture = findAllSharedAttributes(); + } + } else if (clientIsPresent(request) && !sharedIsPresent(request)) { + if (clientIsNotEmpty(request)) { + clientAttributesFuture = findClientAttributes(request); } else { - return systemContext.getAttributesService().findAll(tenantId, deviceId, scope); + clientAttributesFuture = findAllClientAttributes(); } + sharedAttributesFuture = Futures.immediateFuture(Collections.emptyList()); } else { - return systemContext.getAttributesService().findAll(tenantId, deviceId, scope); + if (sharedIsNotEmpty(request)) { + sharedAttributesFuture = findSharedAttributes(request); + } else { + sharedAttributesFuture = findAllSharedAttributes(); + } + clientAttributesFuture = Futures.immediateFuture(Collections.emptyList()); } + return Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)); + } + + private ListenableFuture> findAllSharedAttributes() { + return systemContext.getAttributesService().findAll(tenantId, deviceId, SHARED_SCOPE); + } + + private ListenableFuture> findAllClientAttributes() { + return systemContext.getAttributesService().findAll(tenantId, deviceId, CLIENT_SCOPE); + } + + private ListenableFuture> findSharedAttributes(GetAttributeRequestMsg request) { + return systemContext.getAttributesService().find(tenantId, deviceId, SHARED_SCOPE, getSharedAttributesSet(request)); + } + + private ListenableFuture> findClientAttributes(GetAttributeRequestMsg request) { + return systemContext.getAttributesService().find(tenantId, deviceId, CLIENT_SCOPE, getClientAttributesSet(request)); + } + + private boolean clientIsNotEmpty(GetAttributeRequestMsg request) { + return !getClientAttributesSet(request).isEmpty(); + } + + private boolean sharedIsNotEmpty(GetAttributeRequestMsg request) { + return !getSharedAttributesSet(request).isEmpty(); + } + + private Set getSharedAttributesSet(GetAttributeRequestMsg request) { + return toOptionalSet(request.getSharedAttributeNamesList()).get(); + } + + private Set getClientAttributesSet(GetAttributeRequestMsg request) { + return toOptionalSet(request.getClientAttributeNamesList()).get(); + } + + private boolean sharedIsPresent(GetAttributeRequestMsg request) { + return toOptionalSet(request.getSharedAttributeNamesList()).isPresent(); + } + + private boolean clientIsPresent(GetAttributeRequestMsg request) { + return toOptionalSet(request.getClientAttributeNamesList()).isPresent(); } private void handlePostAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, PostAttributeMsg postAttributes) { @@ -366,7 +426,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { AttributeUpdateNotificationMsg.Builder notification = AttributeUpdateNotificationMsg.newBuilder(); if (msg.isDeleted()) { List sharedKeys = msg.getDeletedKeys().stream() - .filter(key -> DataConstants.SHARED_SCOPE.equals(key.getScope())) + .filter(key -> SHARED_SCOPE.equals(key.getScope())) .map(AttributeKey::getAttributeKey) .collect(Collectors.toList()); if (!sharedKeys.isEmpty()) { @@ -374,7 +434,7 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { hasNotificationData = true; } } else { - if (DataConstants.SHARED_SCOPE.equals(msg.getScope())) { + if (SHARED_SCOPE.equals(msg.getScope())) { List attributes = new ArrayList<>(msg.getValues()); if (attributes.size() > 0) { List sharedUpdated = msg.getValues().stream().map(this::toTsKvProto) From 90643f397c1a83ea9d6b058af80592bc9c6bbc48 Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Mon, 17 Dec 2018 20:24:06 +0200 Subject: [PATCH 04/27] Fixes for entity_views update schemas --- .../main/data/upgrade/2.1.1/schema_update.cql | 7 ------- .../main/data/upgrade/2.1.1/schema_update.sql | 4 +--- .../org/thingsboard/client/tools/RestClient.java | 16 ++++++++++++++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/application/src/main/data/upgrade/2.1.1/schema_update.cql b/application/src/main/data/upgrade/2.1.1/schema_update.cql index 36ac8e4d38..73793c4ea1 100644 --- a/application/src/main/data/upgrade/2.1.1/schema_update.cql +++ b/application/src/main/data/upgrade/2.1.1/schema_update.cql @@ -14,13 +14,6 @@ -- limitations under the License. -- -DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_name; -DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_search_text; -DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_customer; -DROP MATERIALIZED VIEW IF EXISTS thingsboard.entity_view_by_tenant_and_entity_id; - -DROP TABLE IF EXISTS thingsboard.entity_views; - CREATE TABLE IF NOT EXISTS thingsboard.entity_views ( id timeuuid, entity_id timeuuid, diff --git a/application/src/main/data/upgrade/2.1.1/schema_update.sql b/application/src/main/data/upgrade/2.1.1/schema_update.sql index bd2c341e7f..ecf90e01ad 100644 --- a/application/src/main/data/upgrade/2.1.1/schema_update.sql +++ b/application/src/main/data/upgrade/2.1.1/schema_update.sql @@ -14,10 +14,8 @@ -- limitations under the License. -- -DROP TABLE IF EXISTS entity_views; - CREATE TABLE IF NOT EXISTS entity_views ( - id varchar(31) NOT NULL CONSTRAINT entity_view_pkey PRIMARY KEY, + id varchar(31) NOT NULL CONSTRAINT entity_views_pkey PRIMARY KEY, entity_id varchar(31), entity_type varchar(255), tenant_id varchar(31), diff --git a/tools/src/main/java/org/thingsboard/client/tools/RestClient.java b/tools/src/main/java/org/thingsboard/client/tools/RestClient.java index 4c8c0a4f37..14f8f9ffe6 100644 --- a/tools/src/main/java/org/thingsboard/client/tools/RestClient.java +++ b/tools/src/main/java/org/thingsboard/client/tools/RestClient.java @@ -36,6 +36,7 @@ import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.security.DeviceCredentials; +import org.thingsboard.server.common.data.security.DeviceCredentialsType; import java.io.IOException; import java.util.Collections; @@ -120,6 +121,21 @@ public class RestClient implements ClientHttpRequestInterceptor { return restTemplate.postForEntity(baseURL + "/api/device", device, Device.class).getBody(); } + public void deleteDevice(DeviceId deviceId) { + restTemplate.delete(baseURL + "/api/device/" + deviceId.getId().toString()); + } + + public DeviceCredentials updateDeviceCredentials(DeviceId deviceId, String token) { + DeviceCredentials deviceCredentials = getCredentials(deviceId); + deviceCredentials.setCredentialsType(DeviceCredentialsType.ACCESS_TOKEN); + deviceCredentials.setCredentialsId(token); + return saveDeviceCredentials(deviceCredentials); + } + + public DeviceCredentials saveDeviceCredentials(DeviceCredentials deviceCredentials) { + return restTemplate.postForEntity(baseURL + "/api/device/credentials", deviceCredentials, DeviceCredentials.class).getBody(); + } + public Asset createAsset(String name, String type) { Asset asset = new Asset(); asset.setName(name); From 5291afda8a9f39fcc8f03e2f3e5a729369b0d15b Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Tue, 18 Dec 2018 14:49:49 +0200 Subject: [PATCH 05/27] refactoring getAttributes() test --- .../msa/connectivity/HttpClientTest.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java index a5796cc69a..bb3380f554 100644 --- a/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java +++ b/msa/black-box-tests/src/test/java/org/thingsboard/server/msa/connectivity/HttpClientTest.java @@ -28,8 +28,10 @@ import org.thingsboard.server.msa.mapper.WsTelemetryResponse; import java.util.Optional; +import java.util.concurrent.TimeUnit; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.thingsboard.server.common.data.DataConstants.DEVICE; @@ -79,34 +81,39 @@ public class HttpClientTest extends AbstractContainerTest { ResponseEntity.class, accessToken); + Assert.assertTrue(deviceSharedAttributes.getStatusCode().is2xxSuccessful()); + ResponseEntity deviceClientsAttributes = restClient.getRestTemplate() .postForEntity(HTTPS_URL + "/api/v1/" + accessToken + "/attributes/", mapper.readTree(createPayload().toString()), ResponseEntity.class, accessToken); - Assert.assertTrue(deviceSharedAttributes.getStatusCode().is2xxSuccessful()); Assert.assertTrue(deviceClientsAttributes.getStatusCode().is2xxSuccessful()); + TimeUnit.SECONDS.sleep(3); + Optional allOptional = restClient.getAttributes(accessToken, null, null); assertTrue(allOptional.isPresent()); + JsonNode all = allOptional.get(); - assertEquals(all.get("shared"), mapper.readTree(createPayload().toString())); - assertEquals(all.get("client"), mapper.readTree(createPayload().toString())); + assertEquals(2, all.size()); + assertEquals(mapper.readTree(createPayload().toString()), all.get("shared")); + assertEquals(mapper.readTree(createPayload().toString()), all.get("client")); Optional sharedOptional = restClient.getAttributes(accessToken, null, "stringKey"); assertTrue(sharedOptional.isPresent()); JsonNode shared = sharedOptional.get(); assertEquals(shared.get("shared").get("stringKey"), mapper.readTree(createPayload().get("stringKey").toString())); - assertEquals(shared.get("client"), mapper.readTree(createPayload().toString())); + assertFalse(shared.has("client")); Optional clientOptional = restClient.getAttributes(accessToken, "longKey,stringKey", null); assertTrue(clientOptional.isPresent()); JsonNode client = clientOptional.get(); - assertEquals(client.get("shared"), mapper.readTree(createPayload().toString())); - assertEquals(client.get("client").get("longKey"), mapper.readTree(createPayload().get("longKey").toString())); + assertFalse(client.has("shared")); + assertEquals(mapper.readTree(createPayload().get("longKey").toString()), client.get("client").get("longKey")); assertEquals(client.get("client").get("stringKey"), mapper.readTree(createPayload().get("stringKey").toString())); restClient.deleteDevice(device.getId()); From c2d754f9d804cd27209796c2cf579fa390def0e8 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Thu, 20 Dec 2018 16:48:47 +0200 Subject: [PATCH 06/27] refactoring getAttributesKvEntries method --- .../device/DeviceActorMessageProcessor.java | 84 +++++-------------- 1 file changed, 19 insertions(+), 65 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index 6f66a77eb2..b250988369 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -78,7 +78,6 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.function.Consumer; @@ -288,73 +287,36 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { private ListenableFuture>> getAttributesKvEntries(GetAttributeRequestMsg request) { ListenableFuture> clientAttributesFuture; ListenableFuture> sharedAttributesFuture; - if (!clientIsPresent(request) && !sharedIsPresent(request)) { - clientAttributesFuture = findAllClientAttributes(); - sharedAttributesFuture = findAllSharedAttributes(); - } else if (clientIsPresent(request) && sharedIsPresent(request)) { - if (clientIsNotEmpty(request) && sharedIsNotEmpty(request)) { - clientAttributesFuture = findClientAttributes(request); - sharedAttributesFuture = findSharedAttributes(request); - } else { - clientAttributesFuture = findAllClientAttributes(); - sharedAttributesFuture = findAllSharedAttributes(); - } - } else if (clientIsPresent(request) && !sharedIsPresent(request)) { - if (clientIsNotEmpty(request)) { - clientAttributesFuture = findClientAttributes(request); - } else { - clientAttributesFuture = findAllClientAttributes(); - } - sharedAttributesFuture = Futures.immediateFuture(Collections.emptyList()); - } else { - if (sharedIsNotEmpty(request)) { - sharedAttributesFuture = findSharedAttributes(request); - } else { - sharedAttributesFuture = findAllSharedAttributes(); - } + if (listIsEmpty(request.getClientAttributeNamesList()) && listIsEmpty(request.getSharedAttributeNamesList())) { + clientAttributesFuture = findAllAttributesByScope(CLIENT_SCOPE); + sharedAttributesFuture = findAllAttributesByScope(SHARED_SCOPE); + } else if (!listIsEmpty(request.getClientAttributeNamesList()) && !listIsEmpty(request.getSharedAttributeNamesList())) { + clientAttributesFuture = findAttributesByScope(toSet(request.getClientAttributeNamesList()), CLIENT_SCOPE); + sharedAttributesFuture = findAttributesByScope(toSet(request.getSharedAttributeNamesList()), SHARED_SCOPE); + } else if (listIsEmpty(request.getClientAttributeNamesList()) && !listIsEmpty(request.getSharedAttributeNamesList())) { clientAttributesFuture = Futures.immediateFuture(Collections.emptyList()); + sharedAttributesFuture = findAttributesByScope(toSet(request.getSharedAttributeNamesList()), SHARED_SCOPE); + } else { + sharedAttributesFuture = Futures.immediateFuture(Collections.emptyList()); + clientAttributesFuture = findAttributesByScope(toSet(request.getClientAttributeNamesList()), CLIENT_SCOPE); } return Futures.allAsList(Arrays.asList(clientAttributesFuture, sharedAttributesFuture)); } - private ListenableFuture> findAllSharedAttributes() { - return systemContext.getAttributesService().findAll(tenantId, deviceId, SHARED_SCOPE); - } - - private ListenableFuture> findAllClientAttributes() { - return systemContext.getAttributesService().findAll(tenantId, deviceId, CLIENT_SCOPE); - } - - private ListenableFuture> findSharedAttributes(GetAttributeRequestMsg request) { - return systemContext.getAttributesService().find(tenantId, deviceId, SHARED_SCOPE, getSharedAttributesSet(request)); - } - - private ListenableFuture> findClientAttributes(GetAttributeRequestMsg request) { - return systemContext.getAttributesService().find(tenantId, deviceId, CLIENT_SCOPE, getClientAttributesSet(request)); - } - - private boolean clientIsNotEmpty(GetAttributeRequestMsg request) { - return !getClientAttributesSet(request).isEmpty(); - } - - private boolean sharedIsNotEmpty(GetAttributeRequestMsg request) { - return !getSharedAttributesSet(request).isEmpty(); + private ListenableFuture> findAllAttributesByScope(String scope) { + return systemContext.getAttributesService().findAll(tenantId, deviceId, scope); } - private Set getSharedAttributesSet(GetAttributeRequestMsg request) { - return toOptionalSet(request.getSharedAttributeNamesList()).get(); + private ListenableFuture> findAttributesByScope(Set attributesSet, String scope) { + return systemContext.getAttributesService().find(tenantId, deviceId, scope, attributesSet); } - private Set getClientAttributesSet(GetAttributeRequestMsg request) { - return toOptionalSet(request.getClientAttributeNamesList()).get(); + private Set toSet(List strings) { + return new HashSet<>(strings); } - private boolean sharedIsPresent(GetAttributeRequestMsg request) { - return toOptionalSet(request.getSharedAttributeNamesList()).isPresent(); - } - - private boolean clientIsPresent(GetAttributeRequestMsg request) { - return toOptionalSet(request.getClientAttributeNamesList()).isPresent(); + private boolean listIsEmpty(List strings) { + return strings == null || strings.isEmpty(); } private void handlePostAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, PostAttributeMsg postAttributes) { @@ -603,14 +565,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { return json; } - private Optional> toOptionalSet(List strings) { - if (strings == null || strings.isEmpty()) { - return Optional.empty(); - } else { - return Optional.of(new HashSet<>(strings)); - } - } - private void sendToTransport(GetAttributeResponseMsg responseMsg, SessionInfoProto sessionInfo) { DeviceActorToTransportMsg msg = DeviceActorToTransportMsg.newBuilder() .setSessionIdMSB(sessionInfo.getSessionIdMSB()) From 379682a4adde5a0ed5aae8fa87daffd8e1ec8204 Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Thu, 20 Dec 2018 17:20:37 +0200 Subject: [PATCH 07/27] refactoring DeviceActorMessageProcessor.java --- .../actors/device/DeviceActorMessageProcessor.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java index b250988369..c0030cbf6d 100644 --- a/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/device/DeviceActorMessageProcessor.java @@ -25,6 +25,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.protobuf.InvalidProtocolBufferException; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; import org.thingsboard.rule.engine.api.RpcError; import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; import org.thingsboard.rule.engine.api.msg.DeviceNameOrTypeUpdateMsg; @@ -287,13 +288,13 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { private ListenableFuture>> getAttributesKvEntries(GetAttributeRequestMsg request) { ListenableFuture> clientAttributesFuture; ListenableFuture> sharedAttributesFuture; - if (listIsEmpty(request.getClientAttributeNamesList()) && listIsEmpty(request.getSharedAttributeNamesList())) { + if (CollectionUtils.isEmpty(request.getClientAttributeNamesList()) && CollectionUtils.isEmpty(request.getSharedAttributeNamesList())) { clientAttributesFuture = findAllAttributesByScope(CLIENT_SCOPE); sharedAttributesFuture = findAllAttributesByScope(SHARED_SCOPE); - } else if (!listIsEmpty(request.getClientAttributeNamesList()) && !listIsEmpty(request.getSharedAttributeNamesList())) { + } else if (!CollectionUtils.isEmpty(request.getClientAttributeNamesList()) && !CollectionUtils.isEmpty(request.getSharedAttributeNamesList())) { clientAttributesFuture = findAttributesByScope(toSet(request.getClientAttributeNamesList()), CLIENT_SCOPE); sharedAttributesFuture = findAttributesByScope(toSet(request.getSharedAttributeNamesList()), SHARED_SCOPE); - } else if (listIsEmpty(request.getClientAttributeNamesList()) && !listIsEmpty(request.getSharedAttributeNamesList())) { + } else if (CollectionUtils.isEmpty(request.getClientAttributeNamesList()) && !CollectionUtils.isEmpty(request.getSharedAttributeNamesList())) { clientAttributesFuture = Futures.immediateFuture(Collections.emptyList()); sharedAttributesFuture = findAttributesByScope(toSet(request.getSharedAttributeNamesList()), SHARED_SCOPE); } else { @@ -315,10 +316,6 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { return new HashSet<>(strings); } - private boolean listIsEmpty(List strings) { - return strings == null || strings.isEmpty(); - } - private void handlePostAttributesRequest(ActorContext context, SessionInfoProto sessionInfo, PostAttributeMsg postAttributes) { JsonObject json = getJsonObject(postAttributes.getKvList()); TbMsg tbMsg = new TbMsg(UUIDs.timeBased(), SessionMsgType.POST_ATTRIBUTES_REQUEST.name(), deviceId, defaultMetaData.copy(), From dfe2586e616ebbaa1217da0074694d972a9063dc Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Fri, 21 Dec 2018 16:15:17 +0200 Subject: [PATCH 08/27] fix TbGetTelemetryNode (#1353) TbGetTelemetryNode - get start and end ts from metadata --- .../engine/metadata/TbGetTelemetryNode.java | 108 +++++++++++++++--- .../TbGetTelemetryNodeConfiguration.java | 9 ++ .../static/rulenode/rulenode-core-config.js | 8 +- 3 files changed, 106 insertions(+), 19 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index 66569b70bf..b04b5b36c1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -21,8 +21,15 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.google.common.util.concurrent.ListenableFuture; +import lombok.Data; +import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.thingsboard.rule.engine.api.*; +import org.apache.commons.lang3.math.NumberUtils; +import org.thingsboard.rule.engine.api.RuleNode; +import org.thingsboard.rule.engine.api.TbContext; +import org.thingsboard.rule.engine.api.TbNode; +import org.thingsboard.rule.engine.api.TbNodeConfiguration; +import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.util.DonAsynchron; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.kv.BaseReadTsKvQuery; @@ -37,7 +44,9 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; -import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfiguration.*; +import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfiguration.FETCH_MODE_ALL; +import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfiguration.FETCH_MODE_FIRST; +import static org.thingsboard.rule.engine.metadata.TbGetTelemetryNodeConfiguration.MAX_FETCH_SIZE; import static org.thingsboard.server.common.data.kv.Aggregation.NONE; /** @@ -57,8 +66,6 @@ public class TbGetTelemetryNode implements TbNode { private TbGetTelemetryNodeConfiguration config; private List tsKeyNames; - private long startTsOffset; - private long endTsOffset; private int limit; private ObjectMapper mapper; private String fetchMode; @@ -67,8 +74,6 @@ public class TbGetTelemetryNode implements TbNode { public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { this.config = TbNodeUtils.convert(configuration, TbGetTelemetryNodeConfiguration.class); tsKeyNames = config.getLatestTsKeyNames(); - startTsOffset = TimeUnit.valueOf(config.getStartIntervalTimeUnit()).toMillis(config.getStartInterval()); - endTsOffset = TimeUnit.valueOf(config.getEndIntervalTimeUnit()).toMillis(config.getEndInterval()); limit = config.getFetchMode().equals(FETCH_MODE_ALL) ? MAX_FETCH_SIZE : 1; fetchMode = config.getFetchMode(); mapper = new ObjectMapper(); @@ -82,8 +87,8 @@ public class TbGetTelemetryNode implements TbNode { ctx.tellFailure(msg, new IllegalStateException("Telemetry is not selected!")); } else { try { - List queries = buildQueries(); - ListenableFuture> list = ctx.getTimeseriesService().findAll(ctx.getTenantId(), msg.getOriginator(), queries); + checkMetadataKeyPatterns(msg); + ListenableFuture> list = ctx.getTimeseriesService().findAll(ctx.getTenantId(), msg.getOriginator(), buildQueries(msg)); DonAsynchron.withCallback(list, data -> { process(data, msg); TbMsg newMsg = ctx.transformMsg(msg, msg.getType(), msg.getOriginator(), msg.getMetaData(), msg.getData()); @@ -95,10 +100,12 @@ public class TbGetTelemetryNode implements TbNode { } } - private List buildQueries() { - long ts = System.currentTimeMillis(); - long startTs = ts - startTsOffset; - long endTs = ts - endTsOffset; + @Override + public void destroy() { + + } + + private List buildQueries(TbMsg msg) { String orderBy; if (fetchMode.equals(FETCH_MODE_FIRST) || fetchMode.equals(FETCH_MODE_ALL)) { orderBy = "ASC"; @@ -106,7 +113,7 @@ public class TbGetTelemetryNode implements TbNode { orderBy = "DESC"; } return tsKeyNames.stream() - .map(key -> new BaseReadTsKvQuery(key, startTs, endTs, 1, limit, NONE, orderBy)) + .map(key -> new BaseReadTsKvQuery(key, getInterval(msg).getStartTs(), getInterval(msg).getEndTs(), 1, limit, NONE, orderBy)) .collect(Collectors.toList()); } @@ -162,8 +169,79 @@ public class TbGetTelemetryNode implements TbNode { return obj; } - @Override - public void destroy() { + private Interval getInterval(TbMsg msg) { + Interval interval = new Interval(); + if (config.isUseMetadataIntervalPatterns()) { + if (isParsable(msg, config.getStartIntervalPattern())) { + interval.setStartTs(Long.parseLong(TbNodeUtils.processPattern(config.getStartIntervalPattern(), msg.getMetaData()))); + } + if (isParsable(msg, config.getEndIntervalPattern())) { + interval.setEndTs(Long.parseLong(TbNodeUtils.processPattern(config.getEndIntervalPattern(), msg.getMetaData()))); + } + } else { + long ts = System.currentTimeMillis(); + interval.setStartTs(ts - TimeUnit.valueOf(config.getStartIntervalTimeUnit()).toMillis(config.getStartInterval())); + interval.setEndTs(ts - TimeUnit.valueOf(config.getEndIntervalTimeUnit()).toMillis(config.getEndInterval())); + } + return interval; + } + + private boolean isParsable(TbMsg msg, String pattern) { + return NumberUtils.isParsable(TbNodeUtils.processPattern(pattern, msg.getMetaData())); + } + private void checkMetadataKeyPatterns(TbMsg msg) { + isUndefined(msg, config.getStartIntervalPattern(), config.getEndIntervalPattern()); + isInvalid(msg, config.getStartIntervalPattern(), config.getEndIntervalPattern()); } + + private void isUndefined(TbMsg msg, String startIntervalPattern, String endIntervalPattern) { + if (getMetadataValue(msg, startIntervalPattern) == null && getMetadataValue(msg, endIntervalPattern) == null) { + throw new IllegalArgumentException("Message metadata values: '" + + replaceRegex(startIntervalPattern) + "' and '" + + replaceRegex(endIntervalPattern) + "' are undefined"); + } else { + if (getMetadataValue(msg, startIntervalPattern) == null) { + throw new IllegalArgumentException("Message metadata value: '" + + replaceRegex(startIntervalPattern) + "' is undefined"); + } + if (getMetadataValue(msg, endIntervalPattern) == null) { + throw new IllegalArgumentException("Message metadata value: '" + + replaceRegex(endIntervalPattern) + "' is undefined"); + } + } + } + + private void isInvalid(TbMsg msg, String startIntervalPattern, String endIntervalPattern) { + if (getInterval(msg).getStartTs() == null && getInterval(msg).getEndTs() == null) { + throw new IllegalArgumentException("Message metadata values: '" + + replaceRegex(startIntervalPattern) + "' and '" + + replaceRegex(endIntervalPattern) + "' have invalid format"); + } else { + if (getInterval(msg).getStartTs() == null) { + throw new IllegalArgumentException("Message metadata value: '" + + replaceRegex(startIntervalPattern) + "' has invalid format"); + } + if (getInterval(msg).getEndTs() == null) { + throw new IllegalArgumentException("Message metadata value: '" + + replaceRegex(endIntervalPattern) + "' has invalid format"); + } + } + } + + private String getMetadataValue(TbMsg msg, String pattern) { + return msg.getMetaData().getValue(replaceRegex(pattern)); + } + + private String replaceRegex(String pattern) { + return pattern.replaceAll("[${}]", ""); + } + + @Data + @NoArgsConstructor + private static class Interval { + private Long startTs; + private Long endTs; + } + } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeConfiguration.java index 37ce0af42b..31bacf9559 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNodeConfiguration.java @@ -35,6 +35,12 @@ public class TbGetTelemetryNodeConfiguration implements NodeConfiguration
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
{{ 'tb.rulenode.create-customer-if-not-exists' | translate }}
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{scope.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
{{ severity.name | translate}}
tb.rulenode.alarm-severity-required
{{ 'tb.rulenode.propagate' | translate }}
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-type-pattern-required
tb.rulenode.entity-type-pattern-hint
{{ 'tb.rulenode.create-entity-if-not-exists' | translate }}
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.bootstrap-servers-required
tb.rulenode.min-retries-message
tb.rulenode.min-batch-size-bytes-message
tb.rulenode.min-linger-ms-message
tb.rulenode.min-buffer-memory-bytes-message
{{ ackValue }}
tb.rulenode.key-serializer-required
tb.rulenode.value-serializer-required
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-to-string-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.mqtt-topic-pattern-hint
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
tb.rulenode.connect-timeout-required
tb.rulenode.connect-timeout-range
tb.rulenode.connect-timeout-range
{{ \'tb.rulenode.clean-session\' | translate }} {{ \'tb.rulenode.enable-ssl\' | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{credentialsValue.name | translate}}
tb.rulenode.credentials-type-required
tb.rulenode.username-required
tb.rulenode.password-required
'},function(e,t){e.exports="
tb.rulenode.interval-seconds-required
tb.rulenode.min-interval-seconds-message
tb.rulenode.output-timeseries-key-prefix-required
"},function(e,t){e.exports="
tb.rulenode.period-seconds-required
tb.rulenode.min-period-0-seconds-message
tb.rulenode.max-pending-messages-required
tb.rulenode.max-pending-messages-range
tb.rulenode.max-pending-messages-range
"},function(e,t){e.exports='
{{ property }}
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
{{ \'tb.rulenode.automatic-recovery\' | translate }}
tb.rulenode.min-connection-timeout-ms-message
tb.rulenode.min-handshake-timeout-ms-message
'},function(e,t){e.exports='
tb.rulenode.endpoint-url-pattern-required
tb.rulenode.endpoint-url-pattern-hint
{{ type }}
tb.rulenode.headers-hint
'},function(e,t){e.exports="
"},function(e,t){e.exports="
tb.rulenode.timeout-required
tb.rulenode.min-timeout-message
"},function(e,t){e.exports='
{{ \'tb.rulenode.use-system-smtp-settings\' | translate }}
{{smtpProtocol.toUpperCase()}}
tb.rulenode.smtp-host-required
tb.rulenode.smtp-port-required
tb.rulenode.smtp-port-range
tb.rulenode.smtp-port-range
tb.rulenode.timeout-required
tb.rulenode.min-timeout-msec-message
{{ \'tb.rulenode.enable-tls\' | translate }}
'; -},function(e,t){e.exports="
tb.rulenode.topic-arn-pattern-required
tb.rulenode.topic-arn-pattern-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
"},function(e,t){e.exports='
{{ type.name | translate }}
tb.rulenode.queue-url-pattern-required
tb.rulenode.queue-url-pattern-hint
tb.rulenode.min-delay-seconds-message
tb.rulenode.max-delay-seconds-message
tb.rulenode.message-attributes-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
'},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{ (\'relation.search-direction.\' + direction) | translate}}
relation.relation-type
device.device-types
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports='
{{ type }}
tb.rulenode.start-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.end-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
'},function(e,t){e.exports='
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},28,function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
"},function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.from-template-required
tb.rulenode.from-template-hint
tb.rulenode.to-template-required
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.subject-template-required
tb.rulenode.subject-template-hint
tb.rulenode.body-template-required
tb.rulenode.body-template-hint
"},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(6),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(7),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,i){var r=function(r,a,l,s){var u=o.default;a.html(u),r.types=n,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue},r.testDetailsBuildJs=function(e){var n=angular.copy(r.configuration.alarmDetailsBuildJs);i.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(8),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,i){var r=function(r,a,l,s){var u=o.default;a.html(u),r.types=n,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue},r.testDetailsBuildJs=function(e){var n=angular.copy(r.configuration.alarmDetailsBuildJs);i.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(9),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(10),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(11),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,i){var r=function(r,a,l,s){var u=o.default;a.html(u),r.types=n,r.originator=null,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue,r.configuration.originatorId&&r.configuration.originatorType?r.originator={id:r.configuration.originatorId,entityType:r.configuration.originatorType}:r.originator=null,r.$watch("originator",function(e,t){angular.equals(e,t)||(r.originator?(s.$viewValue.originatorId=r.originator.id,s.$viewValue.originatorType=r.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},r.testScript=function(e){var n=angular.copy(r.configuration.jsScript);i.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,s.$setDirty()})},e(a.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r,n(1);var a=n(12),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(65),a=i(r),o=n(46),l=i(o),s=n(51),u=i(s),d=n(48),c=i(d),m=n(47),g=i(m),p=n(54),f=i(p),b=n(60),v=i(b),y=n(61),q=i(y),h=n(59),$=i(h),x=n(53),T=i(x),k=n(63),C=i(k),w=n(64),M=i(w),_=n(58),S=i(_),N=n(55),E=i(N),V=n(62),P=i(V),F=n(57),j=i(F),A=n(56),O=i(A),I=n(45),R=i(I),K=n(66),D=i(K),U=n(50),L=i(U),z=n(49),B=i(z);t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTimeseriesConfig",a.default).directive("tbActionNodeAttributesConfig",l.default).directive("tbActionNodeGeneratorConfig",u.default).directive("tbActionNodeCreateAlarmConfig",c.default).directive("tbActionNodeClearAlarmConfig",g.default).directive("tbActionNodeLogConfig",f.default).directive("tbActionNodeRpcReplyConfig",v.default).directive("tbActionNodeRpcRequestConfig",q.default).directive("tbActionNodeRestApiCallConfig",$.default).directive("tbActionNodeKafkaConfig",T.default).directive("tbActionNodeSnsConfig",C.default).directive("tbActionNodeSqsConfig",M.default).directive("tbActionNodeRabbitMqConfig",S.default).directive("tbActionNodeMqttConfig",E.default).directive("tbActionNodeSendEmailConfig",P.default).directive("tbActionNodeMsgDelayConfig",j.default).directive("tbActionNodeMsgCountConfig",O.default).directive("tbActionNodeAssignToCustomerConfig",R.default).directive("tbActionNodeUnAssignToCustomerConfig",D.default).directive("tbActionNodeDeleteRelationConfig",L.default).directive("tbActionNodeCreateRelationConfig",B.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.ackValues=["all","-1","0","1"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel", -scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(13),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s),i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},i.testScript=function(e){var r=angular.copy(i.configuration.jsScript);n.testNodeScript(e,r,"string",t.instant("tb.rulenode.to-string")+"","ToString",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.jsScript=e,l.$setDirty()})},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}r.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(14),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s),i.$mdExpansionPanel=t,i.ruleNodeTypes=n,i.credentialsTypeChanged=function(){var e=i.configuration.credentials.type;i.configuration.credentials={},i.configuration.credentials.type=e,i.updateValidity()},i.certFileAdded=function(e,t){var n=new FileReader;n.onload=function(n){i.$apply(function(){if(n.target.result){l.$setDirty();var r=n.target.result;r&&r.length>0&&("caCert"==t&&(i.configuration.credentials.caCertFileName=e.name,i.configuration.credentials.caCert=r),"privateKey"==t&&(i.configuration.credentials.privateKeyFileName=e.name,i.configuration.credentials.privateKey=r),"Cert"==t&&(i.configuration.credentials.certFileName=e.name,i.configuration.credentials.cert=r)),i.updateValidity()}})},n.readAsText(e.file)},i.clearCertFile=function(e){l.$setDirty(),"caCert"==e&&(i.configuration.credentials.caCertFileName=null,i.configuration.credentials.caCert=null),"privateKey"==e&&(i.configuration.credentials.privateKeyFileName=null,i.configuration.credentials.privateKey=null),"Cert"==e&&(i.configuration.credentials.certFileName=null,i.configuration.credentials.cert=null),i.updateValidity()},i.updateValidity=function(){var e=!0,t=i.configuration.credentials;t.type==n.mqttCredentialTypes["cert.PEM"].value&&(t.caCert&&t.cert&&t.privateKey||(e=!1)),l.$setValidity("Certs",e)},i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:i}}r.$inject=["$compile","$mdExpansionPanel","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r,n(2);var a=n(15),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(16),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(17),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(18),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(19),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(20),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(21),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.smtpProtocols=["smtp","smtps"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(22),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(23),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(24),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(25),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(26),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(27),o=i(a)},function(e,t){"use strict";function n(e){var t=function(t,n,i,r){n.html("
"),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(28),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(29),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s);var u=186;i.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,u],i.ruleNodeTypes=n,i.aggPeriodTimeUnits={},i.aggPeriodTimeUnits.MINUTES=n.timeUnit.MINUTES,i.aggPeriodTimeUnits.HOURS=n.timeUnit.HOURS,i.aggPeriodTimeUnits.DAYS=n.timeUnit.DAYS,i.aggPeriodTimeUnits.MILLISECONDS=n.timeUnit.MILLISECONDS,i.aggPeriodTimeUnits.SECONDS=n.timeUnit.SECONDS,i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{},link:i}}r.$inject=["$compile","$mdConstant","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(30),o=i(a);n(3)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(73),a=i(r),o=n(74),l=i(o),s=n(70),u=i(s),d=n(75),c=i(d),m=n(69),g=i(m),p=n(76),f=i(p),b=n(71),v=i(b);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",a.default).directive("tbEnrichmentNodeOriginatorFieldsConfig",l.default).directive("tbEnrichmentNodeDeviceAttributesConfig",u.default).directive("tbEnrichmentNodeRelatedAttributesConfig",c.default).directive("tbEnrichmentNodeCustomerAttributesConfig",g.default).directive("tbEnrichmentNodeTenantAttributesConfig",f.default).directive("tbEnrichmentNodeGetTelemetryFromDatabase",v.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(31),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(32),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(33),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(34),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(35),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(81),a=i(r),o=n(79),l=i(o),s=n(82),u=i(s),d=n(77),c=i(d),m=n(80),g=i(m);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",a.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).directive("tbFilterNodeCheckRelationConfig",c.default).directive("tbFilterNodeOriginatorTypeConfig",g.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),r.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),r.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=r,t.removeKeyVal=a,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||r.$setViewValue(t.query)}),r.$render=function(){if(r.$viewValue){var e=r.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(40),o=i(a);n(5)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(41),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,i,r,a){var l=o.default;i.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(i.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(42),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(85),a=i(r),o=n(87),l=i(o),s=n(88),u=i(s);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",a.default).directive("tbTransformationNodeScriptConfig",l.default).directive("tbTransformationNodeToEmailConfig",u.default).name},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var i=function(i,r,a,l){var s=o.default;r.html(s),i.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(i.configuration)}),l.$render=function(){i.configuration=l.$viewValue},i.testScript=function(e){var r=angular.copy(i.configuration.jsScript);n.testNodeScript(e,r,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.jsScript=e,l.$setDirty()})},e(r.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}r.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(43),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,i,r){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(44),o=i(a)},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(92),a=i(r),o=n(78),l=i(o),s=n(72),u=i(s),d=n(86),c=i(d),m=n(52),g=i(m),p=n(68),f=i(p),b=n(84),v=i(b),y=n(67),q=i(y),h=n(83),$=i(h),x=n(91),T=i(x);t.default=angular.module("thingsboard.ruleChain.config",[a.default,l.default,u.default,c.default,g.default]).directive("tbNodeEmptyConfig",f.default).directive("tbRelationsQueryConfig",v.default).directive("tbDeviceRelationsQueryConfig",q.default).directive("tbKvMapConfig",$.default).config(T.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{"create-entity-if-not-exists":"Create new entity if not exists","entity-name-pattern":"Name pattern","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern, use ${metaKeyName} to substitute variables from metadata","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","entity-type-pattern-hint":"Type pattern, use ${metaKeyName} to substitute variables from metadata","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","customer-cache-expiration":"Customers cache expiration time (sec)","customer-name-pattern-hint":"Customer name pattern, use ${metaKeyName} to substitute variables from metadata","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","start-interval":"Start Interval","end-interval":"End Interval","start-interval-time-unit":"Start Interval Time Unit","end-interval-time-unit":"End Interval Time Unit","fetch-mode":"Fetch mode","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Time value should be in a range from 1 to 2147483647'.","start-interval-value-required":"Start interval value is required.","end-interval-value-required":"End interval value is required.",filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","fields-mapping":"Fields mapping","fields-mapping-required":"At least one field mapping should be specified.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","from-template-hint":"From address template, use ${metaKeyName} to substitute variables from metadata","to-template":"To Template","to-template-required":"To Template is required","mail-address-list-template-hint":"Comma separated address list, use ${metaKeyName} to substitute variables from metadata","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","subject-template-hint":"Mail subject template, use ${metaKeyName} to substitute variables from metadata","body-template":"Body Template","body-template-required":"Body Template is required","body-template-hint":"Mail body template, use ${metaKeyName} to substitute variables from metadata","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","endpoint-url-pattern-hint":"HTTP URL address pattern, use ${metaKeyName} to substitute variables from metadata","request-method":"Request method",headers:"Headers","headers-hint":"Use ${metaKeyName} in header/value fields to substitute variables from metadata",header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","topic-pattern-required":"Topic pattern is required","mqtt-topic-pattern-hint":"MQTT topic pattern, use ${metaKeyName} to substitute variables from metadata","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes","min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","topic-arn-pattern-hint":"Topic ARN pattern, use ${metaKeyName} to substitute variables from metadata","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern", -"queue-url-pattern-required":"Queue URL pattern is required","queue-url-pattern-hint":"Queue URL pattern, use ${metaKeyName} to substitute variables from metadata","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","message-attributes":"Message attributes","message-attributes-hint":"Use ${metaKeyName} in name/value fields to substitute variables from metadata","connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"CA certificate file *","private-key":"Private key file *",cert:"Certificate file *","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required."},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};e.translations("en_US",t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){(0,o.default)(e)}r.$inject=["$translateProvider"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var a=n(90),o=i(a)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}},fetchModeType:["FIRST","LAST","ALL"],httpRequestType:["GET","POST","PUT","DELETE"],sqsQueueType:{STANDARD:{name:"tb.rulenode.sqs-queue-standard",value:"STANDARD"},FIFO:{name:"tb.rulenode.sqs-queue-fifo",value:"FIFO"}},timeUnit:{MILLISECONDS:{value:"MILLISECONDS",name:"tb.rulenode.time-unit-milliseconds"},SECONDS:{value:"SECONDS",name:"tb.rulenode.time-unit-seconds"},MINUTES:{value:"MINUTES",name:"tb.rulenode.time-unit-minutes"},HOURS:{value:"HOURS",name:"tb.rulenode.time-unit-hours"},DAYS:{value:"DAYS",name:"tb.rulenode.time-unit-days"}},mqttCredentialTypes:{anonymous:{value:"anonymous",name:"tb.rulenode.credentials-anonymous"},basic:{value:"basic",name:"tb.rulenode.credentials-basic"},"cert.PEM":{value:"cert.PEM",name:"tb.rulenode.credentials-pem"}}}).name}])); +!function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,i){r.apply(this,[e,t,i].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(89)},function(e,t){},1,1,1,1,function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
{{ 'tb.rulenode.create-customer-if-not-exists' | translate }}
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{scope.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
{{ severity.name | translate}}
tb.rulenode.alarm-severity-required
{{ 'tb.rulenode.propagate' | translate }}
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-type-pattern-required
tb.rulenode.entity-type-pattern-hint
{{ 'tb.rulenode.create-entity-if-not-exists' | translate }}
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.bootstrap-servers-required
tb.rulenode.min-retries-message
tb.rulenode.min-batch-size-bytes-message
tb.rulenode.min-linger-ms-message
tb.rulenode.min-buffer-memory-bytes-message
{{ ackValue }}
tb.rulenode.key-serializer-required
tb.rulenode.value-serializer-required
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-to-string-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.mqtt-topic-pattern-hint
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
tb.rulenode.connect-timeout-required
tb.rulenode.connect-timeout-range
tb.rulenode.connect-timeout-range
{{ \'tb.rulenode.clean-session\' | translate }} {{ \'tb.rulenode.enable-ssl\' | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{credentialsValue.name | translate}}
tb.rulenode.credentials-type-required
tb.rulenode.username-required
tb.rulenode.password-required
'},function(e,t){e.exports="
tb.rulenode.interval-seconds-required
tb.rulenode.min-interval-seconds-message
tb.rulenode.output-timeseries-key-prefix-required
"},function(e,t){e.exports="
tb.rulenode.period-seconds-required
tb.rulenode.min-period-0-seconds-message
tb.rulenode.max-pending-messages-required
tb.rulenode.max-pending-messages-range
tb.rulenode.max-pending-messages-range
"},function(e,t){e.exports='
{{ property }}
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
{{ \'tb.rulenode.automatic-recovery\' | translate }}
tb.rulenode.min-connection-timeout-ms-message
tb.rulenode.min-handshake-timeout-ms-message
'},function(e,t){e.exports='
tb.rulenode.endpoint-url-pattern-required
tb.rulenode.endpoint-url-pattern-hint
{{ type }}
tb.rulenode.headers-hint
'},function(e,t){e.exports="
"},function(e,t){e.exports="
tb.rulenode.timeout-required
tb.rulenode.min-timeout-message
"},function(e,t){e.exports='
{{ \'tb.rulenode.use-system-smtp-settings\' | translate }}
{{smtpProtocol.toUpperCase()}}
tb.rulenode.smtp-host-required
tb.rulenode.smtp-port-required
tb.rulenode.smtp-port-range
tb.rulenode.smtp-port-range
tb.rulenode.timeout-required
tb.rulenode.min-timeout-msec-message
{{ \'tb.rulenode.enable-tls\' | translate }}
'; +},function(e,t){e.exports="
tb.rulenode.topic-arn-pattern-required
tb.rulenode.topic-arn-pattern-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
"},function(e,t){e.exports='
{{ type.name | translate }}
tb.rulenode.queue-url-pattern-required
tb.rulenode.queue-url-pattern-hint
tb.rulenode.min-delay-seconds-message
tb.rulenode.max-delay-seconds-message
tb.rulenode.message-attributes-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
'},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{ (\'relation.search-direction.\' + direction) | translate}}
relation.relation-type
device.device-types
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports='
{{ type }} {{ \'tb.rulenode.use-metadata-interval-patterns\' | translate }}
tb.rulenode.start-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.end-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.start-interval-pattern-required
tb.rulenode.start-interval-pattern-hint
tb.rulenode.end-interval-pattern-required
tb.rulenode.end-interval-pattern-hint
'},function(e,t){e.exports='
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},28,function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
"},function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.from-template-required
tb.rulenode.from-template-hint
tb.rulenode.to-template-required
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.subject-template-required
tb.rulenode.subject-template-hint
tb.rulenode.body-template-required
tb.rulenode.body-template-hint
"},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(6),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(7),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n,r){var i=function(i,a,l,s){var u=o.default;a.html(u),i.types=n,i.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(i.configuration)}),s.$render=function(){i.configuration=s.$viewValue},i.testDetailsBuildJs=function(e){var n=angular.copy(i.configuration.alarmDetailsBuildJs);r.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}i.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(8),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n,r){var i=function(i,a,l,s){var u=o.default;a.html(u),i.types=n,i.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(i.configuration)}),s.$render=function(){i.configuration=s.$viewValue},i.testDetailsBuildJs=function(e){var n=angular.copy(i.configuration.alarmDetailsBuildJs);r.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}i.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(9),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(10),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(11),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n,r){var i=function(i,a,l,s){var u=o.default;a.html(u),i.types=n,i.originator=null,i.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(i.configuration)}),s.$render=function(){i.configuration=s.$viewValue,i.configuration.originatorId&&i.configuration.originatorType?i.originator={id:i.configuration.originatorId,entityType:i.configuration.originatorType}:i.originator=null,i.$watch("originator",function(e,t){angular.equals(e,t)||(i.originator?(s.$viewValue.originatorId=i.originator.id,s.$viewValue.originatorType=i.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},i.testScript=function(e){var n=angular.copy(i.configuration.jsScript);r.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],i.ruleNodeId).then(function(e){i.configuration.jsScript=e,s.$setDirty()})},e(a.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}i.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i,n(1);var a=n(12),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(65),a=r(i),o=n(46),l=r(o),s=n(51),u=r(s),d=n(48),c=r(d),m=n(47),g=r(m),p=n(54),f=r(p),b=n(60),v=r(b),y=n(61),q=r(y),h=n(59),$=r(h),x=n(53),T=r(x),k=n(63),C=r(k),w=n(64),M=r(w),_=n(58),S=r(_),N=n(55),E=r(N),P=n(62),V=r(P),F=n(57),j=r(F),A=n(56),I=r(A),O=n(45),K=r(O),R=n(66),D=r(R),U=n(50),L=r(U),z=n(49),B=r(z); +t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTimeseriesConfig",a.default).directive("tbActionNodeAttributesConfig",l.default).directive("tbActionNodeGeneratorConfig",u.default).directive("tbActionNodeCreateAlarmConfig",c.default).directive("tbActionNodeClearAlarmConfig",g.default).directive("tbActionNodeLogConfig",f.default).directive("tbActionNodeRpcReplyConfig",v.default).directive("tbActionNodeRpcRequestConfig",q.default).directive("tbActionNodeRestApiCallConfig",$.default).directive("tbActionNodeKafkaConfig",T.default).directive("tbActionNodeSnsConfig",C.default).directive("tbActionNodeSqsConfig",M.default).directive("tbActionNodeRabbitMqConfig",S.default).directive("tbActionNodeMqttConfig",E.default).directive("tbActionNodeSendEmailConfig",V.default).directive("tbActionNodeMsgDelayConfig",j.default).directive("tbActionNodeMsgCountConfig",I.default).directive("tbActionNodeAssignToCustomerConfig",K.default).directive("tbActionNodeUnAssignToCustomerConfig",D.default).directive("tbActionNodeDeleteRelationConfig",L.default).directive("tbActionNodeCreateRelationConfig",B.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.ackValues=["all","-1","0","1"],t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(13),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var i=angular.copy(r.configuration.jsScript);n.testNodeScript(e,i,"string",t.instant("tb.rulenode.to-string")+"","ToString",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}i.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(14),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s),r.$mdExpansionPanel=t,r.ruleNodeTypes=n,r.credentialsTypeChanged=function(){var e=r.configuration.credentials.type;r.configuration.credentials={},r.configuration.credentials.type=e,r.updateValidity()},r.certFileAdded=function(e,t){var n=new FileReader;n.onload=function(n){r.$apply(function(){if(n.target.result){l.$setDirty();var i=n.target.result;i&&i.length>0&&("caCert"==t&&(r.configuration.credentials.caCertFileName=e.name,r.configuration.credentials.caCert=i),"privateKey"==t&&(r.configuration.credentials.privateKeyFileName=e.name,r.configuration.credentials.privateKey=i),"Cert"==t&&(r.configuration.credentials.certFileName=e.name,r.configuration.credentials.cert=i)),r.updateValidity()}})},n.readAsText(e.file)},r.clearCertFile=function(e){l.$setDirty(),"caCert"==e&&(r.configuration.credentials.caCertFileName=null,r.configuration.credentials.caCert=null),"privateKey"==e&&(r.configuration.credentials.privateKeyFileName=null,r.configuration.credentials.privateKey=null),"Cert"==e&&(r.configuration.credentials.certFileName=null,r.configuration.credentials.cert=null),r.updateValidity()},r.updateValidity=function(){var e=!0,t=r.configuration.credentials;t.type==n.mqttCredentialTypes["cert.PEM"].value&&(t.caCert&&t.cert&&t.privateKey||(e=!1)),l.$setValidity("Certs",e)},r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:r}}i.$inject=["$compile","$mdExpansionPanel","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i,n(2);var a=n(15),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(16),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(17),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"],t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(18),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(19),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(20),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(21),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.smtpProtocols=["smtp","smtps"],t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(22),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(23),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:n}}i.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(24),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(25),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(26),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(27),o=r(a)},function(e,t){"use strict";function n(e){var t=function(t,n,r,i){n.html("
"),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(28),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(29),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s);var u=186;r.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,u],r.ruleNodeTypes=n,r.aggPeriodTimeUnits={},r.aggPeriodTimeUnits.MINUTES=n.timeUnit.MINUTES,r.aggPeriodTimeUnits.HOURS=n.timeUnit.HOURS,r.aggPeriodTimeUnits.DAYS=n.timeUnit.DAYS,r.aggPeriodTimeUnits.MILLISECONDS=n.timeUnit.MILLISECONDS,r.aggPeriodTimeUnits.SECONDS=n.timeUnit.SECONDS,r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{},link:r}}i.$inject=["$compile","$mdConstant","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(30),o=r(a);n(3)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(73),a=r(i),o=n(74),l=r(o),s=n(70),u=r(s),d=n(75),c=r(d),m=n(69),g=r(m),p=n(76),f=r(p),b=n(71),v=r(b);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",a.default).directive("tbEnrichmentNodeOriginatorFieldsConfig",l.default).directive("tbEnrichmentNodeDeviceAttributesConfig",u.default).directive("tbEnrichmentNodeRelatedAttributesConfig",c.default).directive("tbEnrichmentNodeCustomerAttributesConfig",g.default).directive("tbEnrichmentNodeTenantAttributesConfig",f.default).directive("tbEnrichmentNodeGetTelemetryFromDatabase",v.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(31),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(32),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(33),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(34),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(35),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(81),a=r(i),o=n(79),l=r(o),s=n(82),u=r(s),d=n(77),c=r(d),m=n(80),g=r(m);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",a.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).directive("tbFilterNodeCheckRelationConfig",c.default).directive("tbFilterNodeOriginatorTypeConfig",g.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),i.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),i.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=i,t.removeKeyVal=a,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||i.$setViewValue(t.query)}),i.$render=function(){if(i.$viewValue){var e=i.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(40),o=r(a);n(5)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(41),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(42),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(85),a=r(i),o=n(87),l=r(o),s=n(88),u=r(s);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",a.default).directive("tbTransformationNodeScriptConfig",l.default).directive("tbTransformationNodeToEmailConfig",u.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var i=angular.copy(r.configuration.jsScript);n.testNodeScript(e,i,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}i.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(43),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(44),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(92),a=r(i),o=n(78),l=r(o),s=n(72),u=r(s),d=n(86),c=r(d),m=n(52),g=r(m),p=n(68),f=r(p),b=n(84),v=r(b),y=n(67),q=r(y),h=n(83),$=r(h),x=n(91),T=r(x);t.default=angular.module("thingsboard.ruleChain.config",[a.default,l.default,u.default,c.default,g.default]).directive("tbNodeEmptyConfig",f.default).directive("tbRelationsQueryConfig",v.default).directive("tbDeviceRelationsQueryConfig",q.default).directive("tbKvMapConfig",$.default).config(T.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{"create-entity-if-not-exists":"Create new entity if not exists","entity-name-pattern":"Name pattern","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern, use ${metaKeyName} to substitute variables from metadata","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","entity-type-pattern-hint":"Type pattern, use ${metaKeyName} to substitute variables from metadata","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","customer-cache-expiration":"Customers cache expiration time (sec)","customer-name-pattern-hint":"Customer name pattern, use ${metaKeyName} to substitute variables from metadata","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","start-interval":"Start Interval","end-interval":"End Interval","start-interval-time-unit":"Start Interval Time Unit","end-interval-time-unit":"End Interval Time Unit","fetch-mode":"Fetch mode","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Time value should be in a range from 1 to 2147483647'.","start-interval-value-required":"Start interval value is required.","end-interval-value-required":"End interval value is required.",filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","fields-mapping":"Fields mapping","fields-mapping-required":"At least one field mapping should be specified.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","from-template-hint":"From address template, use ${metaKeyName} to substitute variables from metadata","to-template":"To Template","to-template-required":"To Template is required","mail-address-list-template-hint":"Comma separated address list, use ${metaKeyName} to substitute variables from metadata","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","subject-template-hint":"Mail subject template, use ${metaKeyName} to substitute variables from metadata","body-template":"Body Template","body-template-required":"Body Template is required","body-template-hint":"Mail body template, use ${metaKeyName} to substitute variables from metadata","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","endpoint-url-pattern-hint":"HTTP URL address pattern, use ${metaKeyName} to substitute variables from metadata","request-method":"Request method",headers:"Headers","headers-hint":"Use ${metaKeyName} in header/value fields to substitute variables from metadata",header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","topic-pattern-required":"Topic pattern is required","mqtt-topic-pattern-hint":"MQTT topic pattern, use ${metaKeyName} to substitute variables from metadata","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes", +"min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","topic-arn-pattern-hint":"Topic ARN pattern, use ${metaKeyName} to substitute variables from metadata","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","queue-url-pattern-hint":"Queue URL pattern, use ${metaKeyName} to substitute variables from metadata","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","message-attributes":"Message attributes","message-attributes-hint":"Use ${metaKeyName} in name/value fields to substitute variables from metadata","connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"CA certificate file *","private-key":"Private key file *",cert:"Certificate file *","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-interval-patterns":"Use metadata interval patterns","start-interval-pattern":"Start interval pattern","end-interval-pattern":"End interval pattern","start-interval-pattern-required":"Start interval pattern is required","end-interval-pattern-required":"End interval pattern is required","start-interval-pattern-hint":"Start interval pattern, use ${metaKeyName} to substitute variables from metadata","end-interval-pattern-hint":"End interval pattern, use ${metaKeyName} to substitute variables from metadata","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required."},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};e.translations("en_US",t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){(0,o.default)(e)}i.$inject=["$translateProvider"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(90),o=r(a)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}},fetchModeType:["FIRST","LAST","ALL"],httpRequestType:["GET","POST","PUT","DELETE"],sqsQueueType:{STANDARD:{name:"tb.rulenode.sqs-queue-standard",value:"STANDARD"},FIFO:{name:"tb.rulenode.sqs-queue-fifo",value:"FIFO"}},timeUnit:{MILLISECONDS:{value:"MILLISECONDS",name:"tb.rulenode.time-unit-milliseconds"},SECONDS:{value:"SECONDS",name:"tb.rulenode.time-unit-seconds"},MINUTES:{value:"MINUTES",name:"tb.rulenode.time-unit-minutes"},HOURS:{value:"HOURS",name:"tb.rulenode.time-unit-hours"},DAYS:{value:"DAYS",name:"tb.rulenode.time-unit-days"}},mqttCredentialTypes:{anonymous:{value:"anonymous",name:"tb.rulenode.credentials-anonymous"},basic:{value:"basic",name:"tb.rulenode.credentials-basic"},"cert.PEM":{value:"cert.PEM",name:"tb.rulenode.credentials-pem"}}}).name}])); //# sourceMappingURL=rulenode-core-config.js.map \ No newline at end of file From 80af7ebf8d9e5dcb2fe8a9a3b867a2844bfcce97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Sch=C3=B6nebeck?= <30472657+andyesys@users.noreply.github.com> Date: Thu, 20 Dec 2018 14:53:16 +0100 Subject: [PATCH 09/27] Update schema-entities.sql --- dao/src/main/resources/sql/schema-entities.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dao/src/main/resources/sql/schema-entities.sql b/dao/src/main/resources/sql/schema-entities.sql index 6d08611035..7a6ef7bb6d 100644 --- a/dao/src/main/resources/sql/schema-entities.sql +++ b/dao/src/main/resources/sql/schema-entities.sql @@ -72,7 +72,7 @@ CREATE TABLE IF NOT EXISTS attribute_kv ( long_v bigint, dbl_v double precision, last_update_ts bigint, - CONSTRAINT attribute_kv_unq_key UNIQUE (entity_type, entity_id, attribute_type, attribute_key) + CONSTRAINT attribute_kv_pkey PRIMARY KEY (entity_type, entity_id, attribute_type, attribute_key) ); CREATE TABLE IF NOT EXISTS component_descriptor ( @@ -148,7 +148,7 @@ CREATE TABLE IF NOT EXISTS relation ( relation_type_group varchar(255), relation_type varchar(255), additional_info varchar, - CONSTRAINT relation_unq_key UNIQUE (from_id, from_type, relation_type_group, relation_type, to_id, to_type) + CONSTRAINT relation_pkey PRIMARY KEY (from_id, from_type, relation_type_group, relation_type, to_id, to_type) ); CREATE TABLE IF NOT EXISTS tb_user ( From e0a272586e5511dc915c67e201810ae1a614a6f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Sch=C3=B6nebeck?= <30472657+andyesys@users.noreply.github.com> Date: Thu, 20 Dec 2018 14:54:44 +0100 Subject: [PATCH 10/27] Update schema-ts.sql --- dao/src/main/resources/sql/schema-ts.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dao/src/main/resources/sql/schema-ts.sql b/dao/src/main/resources/sql/schema-ts.sql index 53bc15acc3..821e297c19 100644 --- a/dao/src/main/resources/sql/schema-ts.sql +++ b/dao/src/main/resources/sql/schema-ts.sql @@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS ts_kv ( str_v varchar(10000000), long_v bigint, dbl_v double precision, - CONSTRAINT ts_kv_unq_key UNIQUE (entity_type, entity_id, key, ts) + CONSTRAINT ts_kv_pkey PRIMARY KEY (entity_type, entity_id, key, ts) ); CREATE TABLE IF NOT EXISTS ts_kv_latest ( @@ -35,5 +35,5 @@ CREATE TABLE IF NOT EXISTS ts_kv_latest ( str_v varchar(10000000), long_v bigint, dbl_v double precision, - CONSTRAINT ts_kv_latest_unq_key UNIQUE (entity_type, entity_id, key) + CONSTRAINT ts_kv_latest_pkey PRIMARY KEY (entity_type, entity_id, key) ); From adde20bd4f419aea73893a1038f2e08be8e05063 Mon Sep 17 00:00:00 2001 From: dvk2018 Date: Tue, 25 Dec 2018 17:15:57 +0500 Subject: [PATCH 11/27] Update russian locale. --- ui/src/app/locale/locale.constant-ru_RU.json | 1522 ++++++++++-------- 1 file changed, 867 insertions(+), 655 deletions(-) diff --git a/ui/src/app/locale/locale.constant-ru_RU.json b/ui/src/app/locale/locale.constant-ru_RU.json index eb9996d274..07ae86e5a0 100644 --- a/ui/src/app/locale/locale.constant-ru_RU.json +++ b/ui/src/app/locale/locale.constant-ru_RU.json @@ -22,8 +22,9 @@ "update": "Обновить", "remove": "Удалить", "search": "Поиск", + "clear-search": "Очистить", "assign": "Присвоить", - "unassign": "Отменить присвоение", + "unassign": "Отозвать", "share": "Поделиться", "make-private": "Закрыть для общего доступа", "apply": "Применить", @@ -43,6 +44,8 @@ "undo": "Откатить", "copy": "Копировать", "paste": "Вставить", + "copy-reference": "Копировать ссылку", + "paste-reference": "Вставить ссылку", "import": "Импортировать", "export": "Экспортировать", "share-via": "Поделиться в {{provider}}" @@ -83,168 +86,179 @@ "send-test-mail": "Отправить пробное письмо" }, "alarm": { - "alarm": "Alarm", - "alarms": "Alarms", - "select-alarm": "Select alarm", - "no-alarms-matching": "No alarms matching '{{entity}}' were found.", - "alarm-required": "Alarm is required", - "alarm-status": "Alarm status", + "alarm": "Оповещение", + "alarms": "Оповещения", + "select-alarm": "Выбрать оповещение", + "no-alarms-matching": "Оповещения '{{entity}}' не найдены.", + "alarm-required": "Оповещение обязательно", + "alarm-status": "Статус оповещения", "search-status": { - "ANY": "Any", - "ACTIVE": "Active", - "CLEARED": "Cleared", - "ACK": "Acknowledged", - "UNACK": "Unacknowledged" + "ANY": "Все", + "ACTIVE": "Активные", + "CLEARED": "Сброшенные", + "ACK": "Подтвержденные", + "UNACK": "Неподтвержденные" }, "display-status": { - "ACTIVE_UNACK": "Active Unacknowledged", - "ACTIVE_ACK": "Active Acknowledged", - "CLEARED_UNACK": "Cleared Unacknowledged", - "CLEARED_ACK": "Cleared Acknowledged" + "ACTIVE_UNACK": "Активные неподтвержденные", + "ACTIVE_ACK": "Активные подтвержденные", + "CLEARED_UNACK": "Сброшенные неподтвержденные", + "CLEARED_ACK": "Сброшенные подтвержденные" }, - "no-alarms-prompt": "No alarms found", - "created-time": "Created time", - "type": "Type", - "severity": "Severity", - "originator": "Originator", - "originator-type": "Originator type", - "details": "Details", - "status": "Status", - "alarm-details": "Alarm details", - "start-time": "Start time", - "end-time": "End time", - "ack-time": "Acknowledged time", - "clear-time": "Cleared time", - "severity-critical": "Critical", - "severity-major": "Major", - "severity-minor": "Minor", - "severity-warning": "Warning", - "severity-indeterminate": "Indeterminate", - "acknowledge": "Acknowledge", - "clear": "Clear", - "search": "Search alarms", - "selected-alarms": "{ count, plural, 1 {1 alarm} other {# alarms} } selected", - "no-data": "No data to display", - "polling-interval": "Alarms polling interval (sec)", - "polling-interval-required": "Alarms polling interval is required.", - "min-polling-interval-message": "At least 1 sec polling interval is allowed.", - "aknowledge-alarms-title": "Acknowledge { count, plural, 1 {1 alarm} other {# alarms} }", - "aknowledge-alarms-text": "Are you sure you want to acknowledge { count, plural, 1 {1 alarm} other {# alarms} }?", - "clear-alarms-title": "Clear { count, plural, 1 {1 alarm} other {# alarms} }", - "clear-alarms-text": "Are you sure you want to clear { count, plural, 1 {1 alarm} other {# alarms} }?" + "no-alarms-prompt": "Оповещения отсутствуют", + "created-time": "Время создания", + "type": "Тип", + "severity": "Уровень", + "originator": "Инициатор", + "originator-type": "Тип инициатора", + "details": "Подробности", + "status": "Статус", + "alarm-details": "Подробности об оповещении", + "start-time": "Время начала", + "end-time": "Время окончания", + "ack-time": "Время подтверждения", + "clear-time": "Время сброса", + "severity-critical": "Критический", + "severity-major": "Основной", + "severity-minor": "Второстепенный", + "severity-warning": "Предупреждение", + "severity-indeterminate": "Неопределенный", + "acknowledge": "Подтвердить", + "clear": "Сбросить", + "search": "Поиск оповещений", + "selected-alarms": "Выбрано { count, plural, 1 {1 оповещение} few {# оповещения} other {# оповещений} }", + "no-data": "Нет данных для отображения", + "polling-interval": "Интервал опроса оповещений (сек)", + "polling-interval-required": "Интервал опроса оповещений обязателен.", + "min-polling-interval-message": "Минимальный интервал опроса оповещений 1 секунда.", + "aknowledge-alarms-title": "Подтвердить { count, plural, 1 {1 оповещение} other {# оповещений} }", + "aknowledge-alarms-text": "Вы точно хотите подтвердить { count, plural, 1 {1 оповещение} other {# оповещений} }?", + "aknowledge-alarm-title": "Подтвердить оповещение", + "aknowledge-alarm-text": "Вы точно хотите подтвердить оповещение?", + "clear-alarms-title": "Сбросить { count, plural, 1 {1 оповещение} other {# оповещений} }", + "clear-alarms-text": "Вы точно хотите сбросить { count, plural, 1 {1 оповещение} other {# оповещений} }?", + "clear-alarm-title": "Сбросить оповещение", + "clear-alarm-text": "Вы точно хотите сбросить оповещение?", + "alarm-status-filter": "Фильтр оповещений" }, "alias": { - "add": "Add alias", - "edit": "Edit alias", - "name": "Alias name", - "name-required": "Alias name is required", - "duplicate-alias": "Alias with same name is already exists.", - "filter-type-single-entity": "Single entity", - "filter-type-entity-list": "Entity list", - "filter-type-entity-name": "Entity name", - "filter-type-state-entity": "Entity from dashboard state", - "filter-type-state-entity-description": "Entity taken from dashboard state parameters", - "filter-type-asset-type": "Asset type", - "filter-type-asset-type-description": "Assets of type '{{assetType}}'", - "filter-type-asset-type-and-name-description": "Assets of type '{{assetType}}' and with name starting with '{{prefix}}'", - "filter-type-device-type": "Device type", - "filter-type-device-type-description": "Devices of type '{{deviceType}}'", - "filter-type-device-type-and-name-description": "Devices of type '{{deviceType}}' and with name starting with '{{prefix}}'", - "filter-type-relations-query": "Relations query", - "filter-type-relations-query-description": "{{entities}} that have {{relationType}} relation {{direction}} {{rootEntity}}", - "filter-type-asset-search-query": "Asset search query", - "filter-type-asset-search-query-description": "Assets with types {{assetTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}", - "filter-type-device-search-query": "Device search query", - "filter-type-device-search-query-description": "Devices with types {{deviceTypes}} that have {{relationType}} relation {{direction}} {{rootEntity}}", - "entity-filter": "Entity filter", - "resolve-multiple": "Resolve as multiple entities", - "filter-type": "Filter type", - "filter-type-required": "Filter type is required.", - "entity-filter-no-entity-matched": "No entities matching specified filter were found.", - "no-entity-filter-specified": "No entity filter specified", - "root-state-entity": "Use dashboard state entity as root", - "root-entity": "Root entity", - "state-entity-parameter-name": "State entity parameter name", - "default-state-entity": "Default state entity", - "default-entity-parameter-name": "By default", - "max-relation-level": "Max relation level", - "unlimited-level": "Unlimited level", - "state-entity": "Dashboard state entity", - "all-entities": "All entities", - "any-relation": "any" + "add": "Добавить псевдоним", + "edit": "Редактировать псевдоним", + "name": "Псевдоним", + "name-required": "Псевдоним обязателен", + "duplicate-alias": "Такой псевдоним уже существует.", + "filter-type-single-entity": "Отдельный объект", + "filter-type-entity-list": "Список объектов", + "filter-type-entity-name": "Название объекта", + "filter-type-state-entity": "Объект, полученный из дашборда", + "filter-type-state-entity-description": "Объект, полученный из параметров дашборда", + "filter-type-asset-type": "Тип актива", + "filter-type-asset-type-description": "Активы типа '{{assetType}}'", + "filter-type-asset-type-and-name-description": "Активы типа '{{assetType}}' и названием, начинающимся с '{{prefix}}'", + "filter-type-device-type": "Тип устройства", + "filter-type-device-type-description": "Устройства типа '{{deviceType}}'", + "filter-type-device-type-and-name-description": "Устройства типа '{{deviceType}}' и названием, начинающимся с '{{prefix}}'", + "filter-type-entity-view-type": "Тип Представления Объекта", + "filter-type-entity-view-type-description": "Представления Объекта типа '{{entityView}}'", + "filter-type-entity-view-type-and-name-description": "Представления Объекта типа '{{entityView}}' и названием, начинающимся с '{{prefix}}'", + "filter-type-relations-query": "Запрос по типу отношений", + "filter-type-relations-query-description": "{{entities}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", + "filter-type-asset-search-query": "Поисковый запрос по активам", + "filter-type-asset-search-query-description": "Активы типа {{assetTypes}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", + "filter-type-device-search-query": "Поисковый запрос по устройствам", + "filter-type-device-search-query-description": "Устройства типа {{deviceTypes}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", + "filter-type-entity-view-search-query": "Поисковый запрос по представлениям объектов", + "filter-type-entity-view-search-query-description": "Представления объектов типа {{entityViewTypes}}, имеющие отношение типа {{relationType}} {{direction}} {{rootEntity}}", + "entity-filter": "Фильтр объектов", + "resolve-multiple": "Принять как несколько объектов", + "filter-type": "Тип фильтра", + "filter-type-required": "Тип фильтра обязателен.", + "entity-filter-no-entity-matched": "Объекты, соответствующие фильтру, не найдены.", + "no-entity-filter-specified": "Не указан фильтр объектов", + "root-state-entity": "Использовать объект, полученный из дашборда, как корневой", + "root-entity": "Корневой объект", + "state-entity-parameter-name": "Название объекта состояния", + "default-state-entity": "Объект состояния по умолчанию", + "default-entity-parameter-name": "По умолчанию", + "max-relation-level": "Максимальная глубина отношений", + "unlimited-level": "Неограниченная глубина", + "state-entity": "Объект состояния дашборда", + "all-entities": "Все объекты", + "any-relation": "не указано" }, "asset": { - "asset": "Asset", - "assets": "Assets", - "management": "Asset management", - "view-assets": "View Assets", - "add": "Add Asset", - "assign-to-customer": "Assign to customer", - "assign-asset-to-customer": "Assign Asset(s) To Customer", - "assign-asset-to-customer-text": "Please select the assets to assign to the customer", - "no-assets-text": "No assets found", - "assign-to-customer-text": "Please select the customer to assign the asset(s)", - "public": "Public", - "assignedToCustomer": "Assigned to customer", - "make-public": "Make asset public", - "make-private": "Make asset private", - "unassign-from-customer": "Unassign from customer", - "delete": "Delete asset", - "asset-public": "Asset is public", - "asset-type": "Asset type", - "asset-type-required": "Asset type is required.", - "select-asset-type": "Select asset type", - "enter-asset-type": "Enter asset type", - "any-asset": "Any asset", - "no-asset-types-matching": "No asset types matching '{{entitySubtype}}' were found.", - "asset-type-list-empty": "No asset types selected.", - "asset-types": "Asset types", - "name": "Name", - "name-required": "Name is required.", - "description": "Description", - "type": "Type", - "type-required": "Type is required.", - "details": "Details", - "events": "Events", - "add-asset-text": "Add new asset", - "asset-details": "Asset details", - "assign-assets": "Assign assets", - "assign-assets-text": "Assign { count, plural, 1 {1 asset} other {# assets} } to customer", - "delete-assets": "Delete assets", - "unassign-assets": "Unassign assets", - "unassign-assets-action-title": "Unassign { count, plural, 1 {1 asset} other {# assets} } from customer", - "assign-new-asset": "Assign new asset", - "delete-asset-title": "Are you sure you want to delete the asset '{{assetName}}'?", - "delete-asset-text": "Be careful, after the confirmation the asset and all related data will become unrecoverable.", - "delete-assets-title": "Are you sure you want to delete { count, plural, 1 {1 asset} other {# assets} }?", - "delete-assets-action-title": "Delete { count, plural, 1 {1 asset} other {# assets} }", - "delete-assets-text": "Be careful, after the confirmation all selected assets will be removed and all related data will become unrecoverable.", - "make-public-asset-title": "Are you sure you want to make the asset '{{assetName}}' public?", - "make-public-asset-text": "After the confirmation the asset and all its data will be made public and accessible by others.", - "make-private-asset-title": "Are you sure you want to make the asset '{{assetName}}' private?", - "make-private-asset-text": "After the confirmation the asset and all its data will be made private and won't be accessible by others.", - "unassign-asset-title": "Are you sure you want to unassign the asset '{{assetName}}'?", - "unassign-asset-text": "After the confirmation the asset will be unassigned and won't be accessible by the customer.", - "unassign-asset": "Unassign asset", - "unassign-assets-title": "Are you sure you want to unassign { count, plural, 1 {1 asset} other {# assets} }?", - "unassign-assets-text": "After the confirmation all selected assets will be unassigned and won't be accessible by the customer.", - "copyId": "Copy asset Id", - "idCopiedMessage": "Asset Id has been copied to clipboard", - "select-asset": "Select asset", - "no-assets-matching": "No assets matching '{{entity}}' were found.", - "asset-required": "Asset is required", - "name-starts-with": "Asset name starts with" + "asset": "Актив", + "assets": "Активы", + "management": "Управление активами", + "view-assets": "Просмотреть активы", + "add": "Добавить актив", + "assign-to-customer": "Присвоить клиенту", + "assign-asset-to-customer": "Присвоить актив(ы) клиенту", + "assign-asset-to-customer-text": "Пожалуйста, выберите активы, которые нужно присвоить объекту", + "no-assets-text": "Активы не найдены", + "assign-to-customer-text": "Пожалуйста, выберите клиента, которому нужно присвоить актив(ы)", + "public": "Общедоступные", + "assignedToCustomer": "Присвоить клиенту", + "make-public": "Открыть общий доступ к активу", + "make-private": "Закрыть общий доступ к активу", + "unassign-from-customer": "Отозвать у клиента", + "delete": "Удалить актив", + "asset-public": "Актив общедоступный", + "asset-type": "Тип актива", + "asset-type-required": "Тип актива обязателен.", + "select-asset-type": "Выберите тип актива", + "enter-asset-type": "Введите тип актива", + "any-asset": "Любой актив", + "no-asset-types-matching": "Активы типа '{{entitySubtype}}' не найдены.", + "asset-type-list-empty": "Типы активов не выбраны.", + "asset-types": "Типы активов", + "name": "Название", + "name-required": "Название обязательно.", + "description": "Описание", + "type": "Тип", + "type-required": "Тип обязателен.", + "details": "Подробности", + "events": "События", + "add-asset-text": "Добавить новый актив", + "asset-details": "Подробности об активе", + "assign-assets": "Присвоить активы", + "assign-assets-text": "Присвоить { count, plural, 1 {1 актив} few {# актива} other {# активов} } клиенту", + "delete-assets": "Удалить активы", + "unassign-assets": "Отозвать активы", + "unassign-assets-action-title": "Отозвать { count, plural, 1 {1 актив} few {# актива} other {# активов} } у клиента", + "assign-new-asset": "Присвоить новый актив", + "delete-asset-title": "Вы точно хотите удалить '{{assetName}}'?", + "delete-asset-text": "Внимание, после подтверждения актив и все связанные с ним данные будут безвозвратно удалены.", + "delete-assets-title": "Вы точно хотите удалить { count, plural, 1 {1 актив} few {# актива} other {# активов} }", + "delete-assets-action-title": "Удалить { count, plural, 1 {1 актив} few {# актива} other {# активов} }", + "delete-assets-text": "Внимание, после подтверждения выбранные активы и все связанные с ними данные будут безвозвратно удалены.", + "make-public-asset-title": "Вы точно хотите открыть общий доступ к активу '{{assetName}}'?", + "make-public-asset-text": "Внимание, после подтверждения актив и все связанные с ним данные станут общедоступными.", + "make-private-asset-title": "Вы точно хотите закрыть общий доступ к активу '{{assetName}}'?", + "make-private-asset-text": "После подтверждения актив и все связанные с ним данные будут закрыты для общего доступа", + "unassign-asset-title": "Вы точно хотите отозвать актив '{{assetName}}'?", + "unassign-asset-text": "После подтверждения актив будут отозван, и клиент потеряет к нему доступ.", + "unassign-asset": "Отозвать актив", + "unassign-assets-title": "Вы точно хотите отозвать { count, plural, 1 {1 актив} few {# актива} other {# активов} }?", + "unassign-assets-text": "После подтверждения активы будут отозваны, и клиент потеряет к ним доступ.", + "copyId": "Копировать ИД актива", + "idCopiedMessage": "ИД актива скопировано в буфер обмена", + "select-asset": "Выбрать активы", + "no-assets-matching": "Активы, соответствующие '{{entity}}', не найдены.", + "asset-required": "Актив обязателен", + "name-starts-with": "Название актива, начинающееся с" }, "attribute": { "attributes": "Атрибуты", "latest-telemetry": "Последняя телеметрия", - "attributes-scope": "Контекст атрибутов устройства", + "attributes-scope": "Контекст атрибутов объекта", "scope-latest-telemetry": "Последняя телеметрия", "scope-client": "Клиентские атрибуты", "scope-server": "Серверные атрибуты", "scope-shared": "Общие атрибуты", "add": "Добавить атрибут", "key": "Ключ", + "last-update-time": "Последнее обновление", "key-required": "Ключ атрибута обязателен.", "value": "Значение", "value-required": "Значение атрибута обязательно.", @@ -262,36 +276,41 @@ "selected-telemetry": "{ count, plural, 1 {Выбран} other {Выбраны} } { count, plural, 1 {1 параметр} few {# параметра} other {# параметров} } телеметрии" }, "audit-log": { - "audit": "Audit", - "audit-logs": "Audit Logs", - "timestamp": "Timestamp", - "entity-type": "Entity Type", - "entity-name": "Entity Name", - "user": "User", - "type": "Type", - "status": "Status", - "details": "Details", - "type-added": "Added", - "type-deleted": "Deleted", - "type-updated": "Updated", - "type-attributes-updated": "Attributes updated", - "type-attributes-deleted": "Attributes deleted", - "type-rpc-call": "RPC call", - "type-credentials-updated": "Credentials updated", - "type-assigned-to-customer": "Assigned to Customer", - "type-unassigned-from-customer": "Unassigned from Customer", - "type-activated": "Activated", - "type-suspended": "Suspended", - "type-credentials-read": "Credentials read", - "type-attributes-read": "Attributes read", - "status-success": "Success", - "status-failure": "Failure", - "audit-log-details": "Audit log details", - "no-audit-logs-prompt": "No logs found", - "action-data": "Action data", - "failure-details": "Failure details", - "search": "Search audit logs", - "clear-search": "Clear search" + "audit": "Аудит", + "audit-logs": "Логи аудита", + "timestamp": "Время", + "entity-type": "Тип объекта", + "entity-name": "Название объекта", + "user": "Пользователь", + "type": "Тип", + "status": "Статус", + "details": "Подробности", + "type-added": "Добавленный", + "type-deleted": "Удаленный", + "type-updated": "Обновленный", + "type-attributes-updated": "Обновлены атрибуты", + "type-attributes-deleted": "Удалены атрибуты", + "type-rpc-call": "RPC вызов", + "type-credentials-updated": "Обновлены учетные данные", + "type-assigned-to-customer": "Присвоен клиенту", + "type-unassigned-from-customer": "Отозван у клиента", + "type-activated": "Активирован", + "type-suspended": "Приостановлен", + "type-credentials-read": "Чтение учетные данных", + "type-attributes-read": "Чтение атрибутов", + "type-relation-add-or-update": "Обновлены отношения", + "type-relation-delete": "Удалены отношения", + "type-relations-delete": "Удалены все отношения", + "type-alarm-ack": "Подтвержден", + "type-alarm-clear": "Сброшен", + "status-success": "Успех", + "status-failure": "Сбой", + "audit-log-details": "Подробности аудит лога", + "no-audit-logs-prompt": "Логи не найдены", + "action-data": "Данные действия", + "failure-details": "Подробности сбоя", + "search": "Поиск аудит логов", + "clear-search": "Очистить поиск" }, "confirm-on-exit": { "message": "У вас есть несохраненные изменения. Вы точно хотите покинуть эту страницу?", @@ -319,17 +338,22 @@ }, "content-type": { "json": "Json", - "text": "Text", - "binary": "Binary (Base64)" + "text": "Текстовый", + "binary": "Бинарный (Base64)" }, "customer": { + "customer": "Клиент", "customers": "Клиенты", "management": "Управление клиентами", - "dashboard": "Дашборд клиентов", - "dashboards": "Дашборды клиентов", + "dashboard": "Дашборд клиента", + "dashboards": "Дашборды клиента", "devices": "Устройства клиента", + "entity-views": "Представления объектов клиента", + "assets": "Активы клиента", "public-dashboards": "Общедоступные дашборды", "public-devices": "Общедоступные устройства", + "public-assets": "Общедоступные активы", + "public-entity-views": "Общедоступные представления объектов", "add": "Добавить клиента", "delete": "Удалить клиента", "manage-customer-users": "Управление пользователями клиента", @@ -337,31 +361,33 @@ "manage-customer-dashboards": "Управление дашбордами клиента", "manage-public-devices": "Управление общедоступными устройствами", "manage-public-dashboards": "Управление общедоступными дашбордами", + "manage-customer-assets": "Управление активами клиента", + "manage-public-assets": "Управление общедоступными активами", "add-customer-text": "Добавить нового клиента", "no-customers-text": "Клиенты не найдены", "customer-details": "Подробности о клиенте", "delete-customer-title": "Вы точно хотите удалить клиента '{{customerTitle}}'?", - "delete-customer-text": "Внимание, после подтверждения клиент и вся связанная с ним информация будут безвозвратно утеряны.", - "delete-customers-title": "Вы точно хотите удалить { count, plural, one {1 клиента} other {# клиентов} }?", - "delete-customers-action-title": "Удалить { count, plural, one {1 клиента} other {# клиентов} } }", - "delete-customers-text": "Внимание, после подтверждения клиенты и вся связанная с ними информация будут безвозвратно утеряны.", + "delete-customer-text": "Внимание, после подтверждения клиент и все связанные с ним данные будут безвозвратно удалены.", + "delete-customers-title": "Вы точно хотите удалить { count, plural, 1 {1 клиент} few {# клиента} other {# клиентов} }?", + "delete-customers-action-title": "Удалить { count, plural, 1 {1 клиент} few {# клиента} other {# клиентов} }", + "delete-customers-text": "Внимание, после подтверждения выбранные клиенты и все связанные с ними данные будут безвозвратно удалены.", "manage-users": "Управление пользователями", - "manage-assets": "Manage assets", + "manage-assets": "Управление активами", "manage-devices": "Управление устройствами", "manage-dashboards": "Управление дашбордами", "title": "Имя", "title-required": "Название обязательно.", "description": "Описание", - "details": "Details", - "events": "Events", - "copyId": "Copy customer Id", - "idCopiedMessage": "Customer Id has been copied to clipboard", - "select-customer": "Select customer", - "no-customers-matching": "No customers matching '{{entity}}' were found.", - "customer-required": "Customer is required", - "select-default-customer": "Select default customer", - "default-customer": "Default customer", - "default-customer-required": "Default customer is required in order to debug dashboard on Tenant level" + "details": "Подробности", + "events": "События", + "copyId": "Копировать ИД клиента", + "idCopiedMessage": "ИД клиента скопирован в буфер обмена", + "select-customer": "Выбрать клиента", + "no-customers-matching": "Клиенты, соответствующие '{{entity}}', не найдены.", + "customer-required": "Клиент обязателен", + "select-default-customer": "Выбрать клиента по умолчанию", + "default-customer": "Клиент по умолчанию", + "default-customer-required": "Клиент по умолчанию обязателен для отладки дашборда на уровне на уровне Владельца" }, "datetime": { "date-from": "Дата с", @@ -379,9 +405,15 @@ "assign-dashboard-to-customer-text": "Пожалуйста, выберите дашборды, которые нужно прикрепить к клиенту", "assign-to-customer-text": "Пожалуйста, выберите клиента, к которому нужно прикрепить дашборд(ы)", "assign-to-customer": "Прикрепить к клиенту", - "unassign-from-customer": "Открепить от клиента", + "unassign-from-customer": "Отозвать у клиента", "make-public": "Открыть дашборд для общего доступа", "make-private": "Закрыть дашборд для общего доступа", + "manage-assigned-customers": "Управление назначенными клиентами", + "assigned-customers": "Назначенные клиенты", + "assign-to-customers": "Присвоить дашборд(ы) клиенту", + "assign-to-customers-text": "Пожалуйста, выбери клиентов, которым нужно присвоить дашборд(ы)", + "unassign-from-customers": "Отозвать дашборд(ы) у клиентов", + "unassign-from-customers-text": "Пожалуйста, выберите клиентов, у которых нужно отозвать дашборд(ы)", "no-dashboards-text": "Дашборды не найдены", "no-widgets": "Виджеты не сконфигурированы", "add-widget": "Добавить новый виджет", @@ -396,19 +428,20 @@ "add-dashboard-text": "Добавить новый дашборд", "assign-dashboards": "Прикрепить дашборды", "assign-new-dashboard": "Прикрепить новый дашборд", - "assign-dashboards-text": "Прикрепить { count, plural, 1 {1 дашборд} other {# дашборда} } к клиенту", + "assign-dashboards-text": "Прикрепить { count, plural, 1 {1 дашборд} few {# дашборда} other {# дашбордов} } к клиенту", + "unassign-dashboards-action-text": "Отозвать { count, plural, 1 {1 дашборд} few {# дашборда} other {# дашбордов} } у клиента", "delete-dashboards": "Удалить дашборды", - "unassign-dashboards": "Открепить дашборды", - "unassign-dashboards-action-title": "Открепить { count, plural, one {1 дашборд} few {# дашборда} other {# дашбордов} } от клиента", + "unassign-dashboards": "Отозвать дашборды", + "unassign-dashboards-action-title": "Отозвать { count, plural, one {1 дашборд} few {# дашборда} other {# дашбордов} } у клиента", "delete-dashboard-title": "Вы точно хотите удалить дашборд '{{dashboardTitle}}'?", "delete-dashboard-text": "Внимание, после подтверждения дашборд и все связанные с ним данные будут безвозвратно утеряны.", "delete-dashboards-title": "Вы точно хотите удалить { count, plural, one {1 дашборд} few {# дашборда} other {# дашбордов} }?", "delete-dashboards-action-title": "Удалить { count, plural, one {1 дашборд} few {# дашборда} other {# дашбордов} }", "delete-dashboards-text": "Внимание, после подтверждения дашборды и все связанные с ними данные будут безвозвратно утеряны.", - "unassign-dashboard-title": "Вы точно хотите открепить дашборд '{{dashboardTitle}}'?", + "unassign-dashboard-title": "Вы точно хотите отозвать дашборд '{{dashboardTitle}}'?", "unassign-dashboard-text": "После подтверждения дашборд не будет доступен клиенту.", - "unassign-dashboard": "Открепить дашборд", - "unassign-dashboards-title": "Вы точно хотите открепить { count, plural, one {1 дашборд} few {# дашборда} other {# дашбордов} }?", + "unassign-dashboard": "Отозвать дашборд", + "unassign-dashboards-title": "Вы точно хотите отозвать { count, plural, one {1 дашборд} few {# дашборда} other {# дашбордов} }?", "unassign-dashboards-text": "После подтверждения выбранные дашборды не будут доступны клиенту.", "public-dashboard-title": "Теперь дашборд общедоступный", "public-dashboard-text": "Теперь ваш дашборд {{dashboardTitle}} доступен всем по ссылке:", @@ -445,9 +478,17 @@ "vertical-margin-required": "Величина вертикального отступа обязательна.", "min-vertical-margin-message": "Минимальная величина вертикального отступа - 0.", "max-vertical-margin-message": "Максимальная величина вертикального отступа - 50.", + "autofill-height": "Автозаполнение по высоте", + "mobile-layout": "Настройки мобильного режима", + "mobile-row-height": "Высота строки в мобильном режиме, px", + "mobile-row-height-required": "Высота строки в мобильном режиме обязательна.", + "min-mobile-row-height-message": "Минимальная высота строки в мобильном режиме составляет 5 px.", + "max-mobile-row-height-message": "Максимальная высота строки в мобильном режиме составляет 200 px.", "display-title": "Показать название дашборда", + "toolbar-always-open": "Отображать панель инструментов", "title-color": "Цвет названия", - "display-device-selection": "Показать выборку устройств", + "display-dashboards-selection": "Отображать выборку дашбордов", + "display-entities-selection": "Отображать выбору объектов", "display-dashboard-timewindow": "Показать временное окно", "display-dashboard-export": "Показать экспорт", "import": "Импортировать дашборд", @@ -456,66 +497,74 @@ "create-new-dashboard": "Создать новый дашборд", "dashboard-file": "Файл дашборда", "invalid-dashboard-file-error": "Не удалось импортировать дашборд: неизвестная схема данных дашборда.", - "dashboard-import-missing-aliases-title": "Конфигурировать псевдонимы импортированного дашборда", + "dashboard-import-missing-aliases-title": "Настроить псевдонимы импортированного дашборда", "create-new-widget": "Создать новый виджет", - "import-widget": "Импортировать новый виджет", - "widget-file": "Файл виджета", - "invalid-widget-file-error": "Не удалось импортировать виджет: неизвестная схема данных виджета.", - "widget-import-missing-aliases-title": "Конфигурировать псевдонимы импортированного виджета", - "open-toolbar": "Открыть панель инструментов", + "import-widget": "Импортировать виджет", + "widget-file": "Виджет-файл", + "invalid-widget-file-error": "Не удалось импортировать виджет: неправильный формат данных.", + "widget-import-missing-aliases-title": "Настроить псевдонимы, которые использует импортированный виджет", + "open-toolbar": "Открыть панель инструментов дашборда", "close-toolbar": "Закрыть панель инструментов", - "configuration-error": "Ошибка конфигурирования", - "alias-resolution-error-title": "Ошибка конфигурирования псевдонимов дашборда", - "invalid-aliases-config": "Не удалось найти устройства, соответствующие фильтру псевдонимов.
Пожалуйста, свяжитесь с администратором для устранения этой проблемы.", + "configuration-error": "Ошибка в настройках", + "alias-resolution-error-title": "Ошибка в настройках псевдонимов дашборда", + "invalid-aliases-config": "Не удалось найти устройство, соответствующее фильтру псевдонимов.
Пожалуйста, обратитесь к администратору для устранения неполадки.", "select-devices": "Выберите устройства", - "assignedToCustomer": "Прикреплен к клиенту", - "public": "Общедоступный", - "public-link": "Общедоступная ссылка", - "copy-public-link": "Скопировать общедоступную ссылку", - "public-link-copied-message": "Общедоступная ссылка на дашборд скопирована в буфер обмена", - "manage-states": "Manage dashboard states", - "states": "Dashboard states", - "search-states": "Search dashboard states", - "selected-states": "{ count, plural, 1 {1 dashboard state} other {# dashboard states} } selected", - "edit-state": "Edit dashboard state", - "delete-state": "Delete dashboard state", - "add-state": "Add dashboard state", - "state": "Dashboard state", - "state-name": "Name", - "state-name-required": "Dashboard state name is required.", - "state-id": "State Id", - "state-id-required": "Dashboard state id is required.", - "state-id-exists": "Dashboard state with the same id is already exists.", - "is-root-state": "Root state", - "delete-state-title": "Delete dashboard state", - "delete-state-text": "Are you sure you want delete dashboard state with name '{{stateName}}'?", - "show-details": "Show details", - "hide-details": "Hide details", - "select-state": "Select target state", - "state-controller": "State controller" + "assignedToCustomer": "Присвоенные клиенту", + "assignedToCustomers": "Присвоенные клиентам", + "public": "Публичный", + "public-link": "Публичная ссылка", + "copy-public-link": "Копировать публичную ссылку", + "public-link-copied-message": "Публичная ссылка на дашборд скопирована в буфер обмена.", + "manage-states": "Управление состоянием дашборда", + "states": "Состояния дашборда", + "search-states": "Поиск состояния дашборда", + "selected-states": "Выбрано { count, plural, 1 {1 состояние} few {# состояния} other {# состояний} } дашборда", + "edit-state": "Изменить состояние дашборда", + "delete-state": "Удалить состояние дашборда", + "add-state": "Добавить состояние дашборда", + "state": "Состояние дашборда", + "state-name": "Название", + "state-name-required": "Название состояния дашборда обязательно.", + "state-id": "ИД состояния", + "state-id-required": "ИД состояния дашборда обязателен.", + "state-id-exists": "Состояния дашборда с таким именем уже существует.", + "is-root-state": "Корневое состояние", + "delete-state-title": "Удалить состояние дашборда", + "delete-state-text": "Вы точно хотите удалить состояние дашборда '{{stateName}}'?", + "show-details": "Показать подробности", + "hide-details": "Скрыть подробности", + "select-state": "Выбрать состояние", + "state-controller": "Контроллер состояния" }, "datakey": { "settings": "Настройки", "advanced": "Дополнительно", "label": "Метка", "color": "Цвет", - "units": "Special symbol to show next to value", - "decimals": "Number of digits after floating point", + "units": "Укажите символы, которые нужно указывать после значения", + "decimals": "Число знаков после запятой", "data-generation-func": "Функция генерации данных", "use-data-post-processing-func": "Использовать функцию пост-обработки данных", "configuration": "Конфигурация ключа данных", - "timeseries": "Выборка по времени", + "timeseries": "Телеметрия", "attributes": "Атрибуты", - "timeseries-required": "Выборка по времени обязательна.", - "timeseries-or-attributes-required": "Выборка по времени/атрибуты обязательны.", - "maximum-timeseries-or-attributes": "Maximum { count, plural, 1 {1 timeseries/attribute is allowed.} other {# timeseries/attributes are allowed} }", - "alarm-fields-required": "Alarm fields are required.", + "alarm": "Параметры оповещения", + "timeseries-required": "Телеметрия объекта обязательна.", + "timeseries-or-attributes-required": "Телеметрия/атрибуты обязательны.", + "maximum-timeseries-or-attributes": "Максимальное количество параметров телеметрии или атрибутов равно {{count}}", + "alarm-fields-required": "Параметры оповещения обязательны.", "function-types": "Тип функции", "function-types-required": "Тип функции обязателен.", - "maximum-function-types": "Maximum { count, plural, 1 {1 function type is allowed.} other {# function types are allowed} }" + "maximum-function-types": "Максимальное количество типов функции равно {{count}}" + "time-description": "время текущего значения;", + "value-description": "текущее значение;", + "prev-value-description": "результат предыдущего вызова функции;", + "time-prev-description": "время предыдущего значения;", + "prev-orig-value-description": "исходное предыдущее значение;" }, "datasource": { "type": "Тип источника данных", + "name": "Название", "add-datasource-prompt": "Пожалуйста, добавьте источник данных" }, "details": { @@ -537,7 +586,7 @@ "create-new-alias": "Создать новый!", "create-new-key": "Создать новый!", "duplicate-alias-error": "Найден дублирующийся псевдоним '{{alias}}'.
В рамках дашборда псевдонимы устройств должны быть уникальными.", - "configure-alias": "Конфигурировать '{{alias}}' псевдоним", + "configure-alias": "Настроить '{{alias}}' псевдоним", "no-devices-matching": "Устройство '{{entity}}' не найдено.", "alias": "Псевдоним", "alias-required": "Псевдоним устройства обязателен.", @@ -565,9 +614,9 @@ "assign-devices": "Присвоить устройство", "assign-devices-text": "Присвоить { count, plural, one {1 устройство} few {# устройства} other {# устройств} } клиенту", "delete-devices": "Удалить устройства", - "unassign-from-customer": "Отменить присвоение клиенту", - "unassign-devices": "Отменить присвоение устройств", - "unassign-devices-action-title": "Отменить присвоение { count, plural, one {1 устройства} few {# устройств} other {# устройств} } клиенту", + "unassign-from-customer": "Отозвать у клиенту", + "unassign-devices": "Отозвать устройства", + "unassign-devices-action-title": "Отозвать у клиента { count, plural, one {1 устройство} few {# устройства} other {# устройств} }", "assign-new-device": "Присвоить новое устройство", "make-public-device-title": "Вы точно хотите открыть общий доступ к устройству '{{deviceName}}'?", "make-public-device-text": "После подтверждения устройство и все связанные с ним данные будут общедоступными.", @@ -579,10 +628,10 @@ "delete-devices-title": "Вы точно хотите удалить { count, plural, one {1 устройство} few {# устройства} other {# устройств} }?", "delete-devices-action-title": "Удалить { count, plural, one {1 устройство} few {# устройства} other {# устройств} } }", "delete-devices-text": "Внимание, после подтверждения выбранные устройства и все связанные с ними данные будут безвозвратно утеряны..", - "unassign-device-title": "Вы точно хотите отменить присвоение устройства '{{deviceName}}'?", + "unassign-device-title": "Вы точно хотите отозвать устройство '{{deviceName}}'?", "unassign-device-text": "После подтверждения устройство будет недоступно клиенту.", - "unassign-device": "Отменить присвоение устройства", - "unassign-devices-title": "Вы точно хотите отменить присвоение { count, plural, one {1 устройство} few {# устройства} other {# устройств} } }?", + "unassign-device": "Отозвать устройство", + "unassign-devices-title": "Вы точно хотите отозвать { count, plural, one {1 устройство} few {# устройства} other {# устройств} }?", "unassign-devices-text": "После подтверждения выбранные устройства будут недоступны клиенту.", "device-credentials": "Учетные данные устройства", "credentials-type": "Тип учетных данных", @@ -593,6 +642,14 @@ "rsa-key-required": "Открытый ключ RSA обязателен.", "secret": "Секрет", "secret-required": "Секрет обязателен.", + "device-type": "Тип устройства", + "device-type-required": "Тип устройства обязатеен.", + "select-device-type": "Выберите тип устройства", + "enter-device-type": "Введите тип устройства", + "any-device": "Любое устройство", + "no-device-types-matching": "Тип устройства, соответствующий '{{entitySubtype}}', не найден.", + "device-type-list-empty": "Не выбран тип устройства.", + "device-types": "Типы устройств", "name": "Название", "name-required": "Название обязательно.", "description": "Описание", @@ -608,6 +665,7 @@ "is-gateway": "Гейтвей", "public": "Общедоступный", "device-public": "Устройство общедоступно" + "select-device": "Выбрать устройство" }, "dialog": { "close": "Закрыть диалог" @@ -618,100 +676,200 @@ "unknown-error": "Неизвестная ошибка" }, "entity": { - "entity": "Entity", - "entities": "Entities", - "aliases": "Entity aliases", - "entity-alias": "Entity alias", - "unable-delete-entity-alias-title": "Unable to delete entity alias", - "unable-delete-entity-alias-text": "Entity alias '{{entityAlias}}' can't be deleted as it used by the following widget(s):
{{widgetsList}}", - "duplicate-alias-error": "Duplicate alias found '{{alias}}'.
Entity aliases must be unique whithin the dashboard.", - "missing-entity-filter-error": "Filter is missing for alias '{{alias}}'.", - "configure-alias": "Configure '{{alias}}' alias", - "alias": "Alias", - "alias-required": "Entity alias is required.", - "remove-alias": "Remove entity alias", - "add-alias": "Add entity alias", - "entity-list": "Entity list", - "entity-type": "Entity type", - "entity-types": "Entity types", - "entity-type-list": "Entity type list", - "any-entity": "Any entity", - "enter-entity-type": "Enter entity type", - "no-entities-matching": "No entities matching '{{entity}}' were found.", - "no-entity-types-matching": "No entity types matching '{{entityType}}' were found.", - "name-starts-with": "Name starts with", - "use-entity-name-filter": "Use filter", - "entity-list-empty": "No entities selected.", - "entity-type-list-empty": "No entity types selected.", - "entity-name-filter-required": "Entity name filter is required.", - "entity-name-filter-no-entity-matched": "No entities starting with '{{entity}}' were found.", - "all-subtypes": "All", - "select-entities": "Select entities", - "no-aliases-found": "No aliases found.", - "no-alias-matching": "'{{alias}}' not found.", - "create-new-alias": "Create a new one!", - "key": "Key", - "key-name": "Key name", - "no-keys-found": "No keys found.", - "no-key-matching": "'{{key}}' not found.", - "create-new-key": "Create a new one!", - "type": "Type", - "type-required": "Entity type is required.", - "type-device": "Device", - "type-devices": "Devices", - "list-of-devices": "{ count, plural, 1 {One device} other {List of # devices} }", - "device-name-starts-with": "Devices whose names start with '{{prefix}}'", - "type-asset": "Asset", - "type-assets": "Assets", - "list-of-assets": "{ count, plural, 1 {One asset} other {List of # assets} }", - "asset-name-starts-with": "Assets whose names start with '{{prefix}}'", - "type-rule": "Rule", - "type-rules": "Rules", - "list-of-rules": "{ count, plural, 1 {One rule} other {List of # rules} }", - "rule-name-starts-with": "Rules whose names start with '{{prefix}}'", - "type-plugin": "Plugin", - "type-plugins": "Plugins", - "list-of-plugins": "{ count, plural, 1 {One plugin} other {List of # plugins} }", - "plugin-name-starts-with": "Plugins whose names start with '{{prefix}}'", - "type-tenant": "Tenant", - "type-tenants": "Tenants", - "list-of-tenants": "{ count, plural, 1 {One tenant} other {List of # tenants} }", - "tenant-name-starts-with": "Tenants whose names start with '{{prefix}}'", - "type-customer": "Customer", - "type-customers": "Customers", - "list-of-customers": "{ count, plural, 1 {One customer} other {List of # customers} }", - "customer-name-starts-with": "Customers whose names start with '{{prefix}}'", - "type-user": "User", - "type-users": "Users", - "list-of-users": "{ count, plural, 1 {One user} other {List of # users} }", - "user-name-starts-with": "Users whose names start with '{{prefix}}'", - "type-dashboard": "Dashboard", - "type-dashboards": "Dashboards", - "list-of-dashboards": "{ count, plural, 1 {One dashboard} other {List of # dashboards} }", - "dashboard-name-starts-with": "Dashboards whose names start with '{{prefix}}'", - "type-alarm": "Alarm", - "type-alarms": "Alarms", - "list-of-alarms": "{ count, plural, 1 {One alarms} other {List of # alarms} }", - "alarm-name-starts-with": "Alarms whose names start with '{{prefix}}'", - "type-rulechain": "Rule chain", - "type-rulechains": "Rule chains", - "list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }", - "rulechain-name-starts-with": "Rule chains whose names start with '{{prefix}}'", - "type-current-customer": "Current Customer", - "search": "Search entities", - "selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } selected", - "entity-name": "Entity name", - "details": "Entity details", - "no-entities-prompt": "No entities found", - "no-data": "No data to display" + "entity": "Объект", + "entities": "Объекты", + "aliases": "Псевдонимы объекта", + "entity-alias": "Псевдоним объекта", + "unable-delete-entity-alias-title": "Не удалось удалить псевдоним объекта", + "unable-delete-entity-alias-text": "Псевдоним объекта '{{entityAlias}}' не может быть удален, так как используется следующим(и) виджетом(ами):
{{widgetsList}}", + "duplicate-alias-error": "Найден дубликат псевдонима '{{alias}}'.
В рамках одного дашборда псевдонимы объектов должны быть уникальными.", + "missing-entity-filter-error": "Отсутствует фильтр для псевдонима '{{alias}}'.", + "configure-alias": "Настроить псевдоним '{{alias}}'", + "alias": "Псевдоним", + "alias-required": "Псевдоним объекта обязателен.", + "remove-alias": "Убрать псевдоним объекта", + "add-alias": "Добавить псевдоним объекта", + "entity-list": "Список объектов", + "entity-type": "Тип объекта", + "entity-types": "Типы объекта", + "entity-type-list": "Список типов объекта", + "any-entity": "Любой объект", + "enter-entity-type": "Введите тип объекта", + "no-entities-matching": "Объекты, соответствующие '{{entity}}', не найдены.", + "no-entity-types-matching": "Типы объектов, соответствующие '{{entityType}}', не найдены.", + "name-starts-with": "Название, начинающееся с", + "use-entity-name-filter": "Использовать фильтр", + "entity-list-empty": "Не выбраны объекты.", + "entity-type-list-empty": "Не выбраны типы объекта.", + "entity-name-filter-required": "Фильтр по названию объекта обязателен.", + "entity-name-filter-no-entity-matched": "Объекты, чье название начинается с '{{entity}}', не найдены.", + "all-subtypes": "Все", + "select-entities": "Выберите объекты", + "no-aliases-found": "Псевдонимы не найдены.", + "no-alias-matching": "Псевдоним '{{alias}}' не найден.", + "create-new-alias": "Создать новый!", + "key": "Ключ", + "key-name": "Название ключа", + "no-keys-found": "Ключ не найден.", + "no-key-matching": "Ключ '{{key}}' не найден.", + "create-new-key": "Создать новый!", + "type": "Тип", + "type-required": "Тип объекта обязателен.", + "type-device": "Устройство", + "type-devices": "Устройства", + "list-of-devices": "{ count, plural, 1 {Одно устройство} other {Список из # устройств} }", + "device-name-starts-with": "Устройства, чьи название начинается с '{{prefix}}'", + "type-asset": "Актив", + "type-assets": "Активы", + "list-of-assets": "{ count, plural, 1 {Один актив} other {Список из # активов} }", + "asset-name-starts-with": "Активы, чьи название начинается с '{{prefix}}'", + "type-entity-view": "Представление Объекта", + "type-entity-views": "Представления Объекта", + "list-of-entity-views": "{ count, plural, 1 {Одно представление объекта} other {Список из # представлений объекта} }", + "entity-view-name-starts-with": "Представления Объекта, чьи название начинается с '{{prefix}}'", + "type-rule": "Правило", + "type-rules": "Правила", + "list-of-rules": "{ count, plural, 1 {Одно правило} other {Список из # правил} }", + "rule-name-starts-with": "Правила, чьи названия начинаются с '{{prefix}}'", + "type-plugin": "Плагин", + "type-plugins": "Плагины", + "list-of-plugins": "{ count, plural, 1 {Один плагин} other {Список из # плагинов} }", + "plugin-name-starts-with": "Плагины, чьи имена начинаются с '{{prefix}}'", + "type-tenant": "Владелец", + "type-tenants": "Владельцы", + "list-of-tenants": "{ count, plural, 1 {Один владелец} other {Список из # владельцев} }", + "tenant-name-starts-with": "Владельцы, чьи имена начинаются с '{{prefix}}'", + "type-customer": "Клиент", + "type-customers": "Клиенты", + "list-of-customers": "{ count, plural, 1 {Один клиент} other {Список из # клиентов} }", + "customer-name-starts-with": "Клиенты, чьи имена начинаются с '{{prefix}}'", + "type-user": "Пользователь", + "type-users": "Пользователи", + "list-of-users": "{ count, plural, 1 {Один пользователь} other {Список из # пользователей} }", + "user-name-starts-with": "Пользователи, чьи имена начинаются с '{{prefix}}'", + "type-dashboard": "Дашборд", + "type-dashboards": "Дашборды", + "list-of-dashboards": "{ count, plural, 1 {Один дашборд} other {Список из # дашбордов} }", + "dashboard-name-starts-with": "Дашборды, чьи названия начинаются с '{{prefix}}'", + "type-alarm": "Оповещение", + "type-alarms": "Оповещения", + "list-of-alarms": "{ count, plural, 1 {Одно оповещение} other {Список из # оповещений} }", + "alarm-name-starts-with": "Оповещения, чьи названия начинаются с '{{prefix}}'", + "type-rulechain": "Цепочка правил", + "type-rulechains": "Цепочки правил", + "list-of-rulechains": "{ count, plural, 1 {Одна цепочка правил} other {Список из # цепочек правил} }", + "rulechain-name-starts-with": "Цепочки правил, чьи названия начинаются с '{{prefix}}'", + "type-rulenode": "Правило", + "type-rulenodes": "Правила", + "list-of-rulenodes": "{ count, plural, 1 {Одно правило} other {Список из # правил} }", + "rulenode-name-starts-with": "Правила, чьи названия начинаются с '{{prefix}}'", + "type-current-customer": "Текущий клиент", + "search": "Поиск объектов", + "selected-entities": "Выбран(ы) { count, plural, 1 {1 объект} few {# объекта} other {# объектов} }", + "entity-name": "Название объекта", + "details": "Подробности об объекте", + "no-entities-prompt": "Объекты не найдены", + "no-data": "Нет данных для отображения", + "columns-to-display": "Отобразить следующие колонки" + }, + "entity-view": { + "entity-view": "Представление Объекта", + "entity-view-required": "Представление объекта обязательно.", + "entity-views": "Представления Объектов", + "management": "Управление представлениями объектов", + "view-entity-views": "Просмотр представлений объектов", + "entity-view-alias": "Псевдоним Представления Объекта", + "aliases": "Псевдонимы Представления Объекта", + "no-alias-matching": "Псевдоним '{{alias}}' не найден.", + "no-aliases-found": "Псевдонимы не найдены.", + "no-key-matching": "Ключ '{{key}}' не найден.", + "no-keys-found": "Ключи не найдены.", + "create-new-alias": "Создать новый!", + "create-new-key": "Создать новый!", + "duplicate-alias-error": "Найден дубликат псевдонима '{{alias}}'.
В рамках одного дашборда псевдонимы представлений объектов должны быть уникальными.", + "configure-alias": "Настроить псевдоним '{{alias}}'", + "no-entity-views-matching": "Объекты, соответствующие '{{entity}}', не найдены.", + "alias": "Псевдонимы", + "alias-required": "Псевдоним представления объекта обязателен.", + "remove-alias": "Убрать псевдоним представления объекта", + "add-alias": "Добавить псевдоним представления объекта", + "name-starts-with": "Представления объектов, чьи название начинается с", + "entity-view-list": "Список представлений объектов", + "use-entity-view-name-filter": "Использовать фильтр", + "entity-view-list-empty": "Не выбраны представления объектов.", + "entity-view-name-filter-required": "Для представлений объектов фильтр по названиям обязателен.", + "entity-view-name-filter-no-entity-view-matched": "Представление объектов, чьи название начинаются с '{{entityView}}', не найдены.", + "add": "Представление объекта", + "assign-to-customer": "Назначить клиенту", + "assign-entity-view-to-customer": "Назначить представление(я) объекта(ов) клиенту", + "assign-entity-view-to-customer-text": "Пожалуйста, выберите представления объектов, которые нужно назначить клиенту", + "no-entity-views-text": "Представления объектов не найдены", + "assign-to-customer-text": "Пожалуйста, выберите клиента, которому нужно назначить представления объектов", + "entity-view-details": "Подробности о представлении объекта", + "add-entity-view-text": "Добавить новое представление объекта", + "delete": "Удалить представление объекта", + "assign-entity-views": "Назначить представления объектов", + "assign-entity-views-text": "Назначить клиенту { count, plural, 1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }", + "delete-entity-views": "Удалить представления объектов", + "unassign-from-customer": "Отозвать у клиента", + "unassign-entity-views": "Отозвать представления объектов", + "unassign-entity-views-action-title": "Отозвать у клиента { count, plural, 1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }", + "assign-new-entity-view": "Назначит новое представление объекта", + "delete-entity-view-title": "Вы точно хотите удалить представление объекта '{{entityViewName}}'?", + "delete-entity-view-text": "Внимание, после подтверждения представление объекта и все связанные с ним данные будут безвозвратно удалены.", + "delete-entity-views-title": "Вы точно хотите удалить { count, plural, 1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }?", + "delete-entity-views-action-title": "Удалить { count, plural, 1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }", + "delete-entity-views-text": "Внимание, после подтверждения выбранные представления объектов и все связанные с ними данные будут безвозвратно удалены.", + "unassign-entity-view-title": "Вы точно хотите отозвать представление объекта '{{entityViewName}}'?", + "unassign-entity-view-text": "После подтверждение представление объекта будет недоступно клиенту.", + "unassign-entity-view": "Отозвать представление объекта", + "unassign-entity-views-title": "Вы точно хотите отозвать { count, plural, 1 {1 представление объекта} few {# представления объектов} other {# представлений объектов} }?", + "unassign-entity-views-text": "После подтверждение выбранные представления объектов будет недоступно клиенту.", + "entity-view-type": "Тип представления объекта", + "entity-view-type-required": "Тип представления объекта обязателен.", + "select-entity-view-type": "Выберите тип представления объекта", + "enter-entity-view-type": "Введите тип представления объекта", + "any-entity-view": "Любое представление объекта", + "no-entity-view-types-matching": "Типы представления объекта, соответствующие '{{entitySubtype}}', не найдены.", + "entity-view-type-list-empty": "Не выбраны типы представления объекта.", + "entity-view-types": "Типы представления объекта", + "name": "Название", + "name-required": "Название обязательно.", + "description": "Описание", + "events": "События", + "details": "Подробности", + "copyId": "Копировать ИД представление объекта", + "assignedToCustomer": "Назначенные клиенту", + "unable-entity-view-device-alias-title": "Не удалось удалить псевдоним представления объекта", + "unable-entity-view-device-alias-text": "Не удалось удалить псевдоним устройства '{{entityViewAlias}}', т.к. он используется следующими виджетами:
{{widgetsList}}", + "select-entity-view": "Выбрать представление объекта", + "make-public": "Открыть общий доступ к представлению объекта", + "start-date": "Дата начала", + "start-ts": "Время начала", + "end-date": "Дата окончания", + "end-ts": "Время окончания", + "date-limits": "Временной лимит", + "client-attributes": "Клиентские атрибуты", + "shared-attributes": "Общие атрибуты", + "server-attributes": "Серверные атрибуты", + "timeseries": "Телеметрия", + "client-attributes-placeholder": "Клиентские атрибуты", + "shared-attributes-placeholder": "Общие атрибуты", + "server-attributes-placeholder": "Серверные атрибуты", + "timeseries-placeholder": "Телеметрия", + "target-entity": "Целевой объект", + "attributes-propagation": "Пробросить атрибуты", + "attributes-propagation-hint": "Представление объекта автоматически копирует указанные атрибуты с Целевого Объекта каждый раз, когда вы сохраняете или обновляете это представление. В целях производительности атрибуты целевого объекта не пробрасываются в представление объекта на каждом их изменении. Вы можете включить автоматический проброс, настроив в вашей цепочке правило \"copy to view\" и соединив его с сообщениями типа \"Post attributes\" и \"Attributes Updated\".", + "timeseries-data": "Данные телеметрии", + "timeseries-data-hint": "Настроить ключи данных телеметрии целевого объекта, которые будут доступны представлению объекта. Эти данные только для чтения." }, "event": { "event-type": "Тип события", "type-error": "Ошибка", "type-lc-event": "Событие жизненного цикла", "type-stats": "Статистика", - "type-debug-rule-node": "Debug", - "type-debug-rule-chain": "Debug", + "type-debug-rule-node": "Отладка", + "type-debug-rule-chain": "Отладка", "no-events-prompt": "События не найдены", "error": "Ошибка", "alarm": "Аварийное оповещение", @@ -719,14 +877,14 @@ "server": "Сервер", "body": "Тело", "method": "Метод", - "type": "Type", - "entity": "Entity", - "message-id": "Message Id", - "message-type": "Message Type", - "data-type": "Data Type", - "relation-type": "Relation Type", - "metadata": "Metadata", - "data": "Data", + "type": "Тип", + "entity": "Объект", + "message-id": "ИД сообщения", + "message-type": "Тип сообщения", + "data-type": "Тип данных", + "relation-type": "Тип отношения", + "metadata": "Метаданные", + "data": "Данные", "event": "Событие", "status": "Статус", "success": "Успех", @@ -735,161 +893,161 @@ "errors-occurred": "Возникли ошибки" }, "extension": { - "extensions": "Extensions", - "selected-extensions": "{ count, plural, 1 {1 extension} other {# extensions} } selected", - "type": "Type", - "key": "Key", - "value": "Value", - "id": "Id", - "extension-id": "Extension id", - "extension-type": "Extension type", + "extensions": "Расширение", + "selected-extensions": "Выбрано { count, plural, 1 {1 расширение} few {# расширения} other {# расширений} }", + "type": "Тип", + "key": "Ключ", + "value": "Значение", + "id": "ИД", + "extension-id": "ИД расширения", + "extension-type": "Тип расширения", "transformer-json": "JSON *", - "unique-id-required": "Current extension id already exists.", - "delete": "Delete extension", - "add": "Add extension", - "edit": "Edit extension", - "delete-extension-title": "Are you sure you want to delete the extension '{{extensionId}}'?", - "delete-extension-text": "Be careful, after the confirmation the extension and all related data will become unrecoverable.", - "delete-extensions-title": "Are you sure you want to delete { count, plural, 1 {1 extension} other {# extensions} }?", - "delete-extensions-text": "Be careful, after the confirmation all selected extensions will be removed.", - "converters": "Converters", - "converter-id": "Converter id", - "configuration": "Configuration", - "converter-configurations": "Converter configurations", - "token": "Security token", - "add-converter": "Add converter", - "add-config": "Add converter configuration", - "device-name-expression": "Device name expression", - "device-type-expression": "Device type expression", - "custom": "Custom", + "unique-id-required": "Такое ИД расширения уже существует.", + "delete": "Удалить расширение", + "add": "Добавить расширение", + "edit": "Редактировать расширение", + "delete-extension-title": "Вы точно хотите удалить расширение '{{extensionId}}'?", + "delete-extension-text": "Внимание, после подтверждения расширение и все связанные с ним данные будут безвозвратно удалены.", + "delete-extensions-title": "Вы точно хотите удалить { count, plural, 1 {1 расширение} few {# расширения} other {# расширений} }?", + "delete-extensions-text": "Внимание, после подтверждения выбранные расширения будут удалены.", + "converters": "Конвертеры", + "converter-id": "ИД конвертера", + "configuration": "Конфигурация", + "converter-configurations": "Конфигурация конвертера", + "token": "Токен безопасности", + "add-converter": "Добавить конвертер", + "add-config": "Добавить конфигурацию конвертера", + "device-name-expression": "Маска названия устройства", + "device-type-expression": "Маска типа устройства", + "custom": "Пользовательский", "to-double": "To Double", - "transformer": "Transformer", - "json-required": "Transformer json is required.", - "json-parse": "Unable to parse transformer json.", - "attributes": "Attributes", - "add-attribute": "Add attribute", - "add-map": "Add mapping element", - "timeseries": "Timeseries", - "add-timeseries": "Add timeseries", - "field-required": "Field is required", - "brokers": "Brokers", - "add-broker": "Add broker", - "host": "Host", - "port": "Port", - "port-range": "Port should be in a range from 1 to 65535.", - "ssl": "Ssl", - "credentials": "Credentials", - "username": "Username", - "password": "Password", - "retry-interval": "Retry interval in milliseconds", - "anonymous": "Anonymous", - "basic": "Basic", + "transformer": "Преобразователь", + "json-required": "JSON преобразователя обязателен.", + "json-parse": "Не удалось распознать JSON преобразователя.", + "attributes": "Атрибуты", + "add-attribute": "Добавить атрибут", + "add-map": "Добавить элемент сопоставления", + "timeseries": "Телеметрия", + "add-timeseries": "Добавить параметр телеметрии", + "field-required": "Параметр обязателен", + "brokers": "Брокеры", + "add-broker": "Добавить брокер", + "host": "Хост", + "port": "Порт", + "port-range": "Значение порта лежит в диапазоне от 1 до 65535.", + "ssl": "SSL", + "credentials": "Учетные данные", + "username": "Имя пользователя", + "password": "Пароль", + "retry-interval": "Интервал повтора в миллисекундах", + "anonymous": "Анонимный", + "basic": "Общий", "pem": "PEM", - "ca-cert": "CA certificate file *", - "private-key": "Private key file *", - "cert": "Certificate file *", - "no-file": "No file selected.", - "drop-file": "Drop a file or click to select a file to upload.", - "mapping": "Mapping", - "topic-filter": "Topic filter", - "converter-type": "Converter type", - "converter-json": "Json", - "json-name-expression": "Device name json expression", - "topic-name-expression": "Device name topic expression", - "json-type-expression": "Device type json expression", - "topic-type-expression": "Device type topic expression", - "attribute-key-expression": "Attribute key expression", - "attr-json-key-expression": "Attribute key json expression", - "attr-topic-key-expression": "Attribute key topic expression", - "request-id-expression": "Request id expression", - "request-id-json-expression": "Request id json expression", - "request-id-topic-expression": "Request id topic expression", - "response-topic-expression": "Response topic expression", - "value-expression": "Value expression", - "topic": "Topic", - "timeout": "Timeout in milliseconds", - "converter-json-required": "Converter json is required.", - "converter-json-parse": "Unable to parse converter json.", - "filter-expression": "Filter expression", - "connect-requests": "Connect requests", - "add-connect-request": "Add connect request", - "disconnect-requests": "Disconnect requests", - "add-disconnect-request": "Add disconnect request", - "attribute-requests": "Attribute requests", - "add-attribute-request": "Add attribute request", - "attribute-updates": "Attribute updates", - "add-attribute-update": "Add attribute update", - "server-side-rpc": "Server side RPC", - "add-server-side-rpc-request": "Add server-side RPC request", - "device-name-filter": "Device name filter", - "attribute-filter": "Attribute filter", - "method-filter": "Method filter", - "request-topic-expression": "Request topic expression", - "response-timeout": "Response timeout in milliseconds", - "topic-expression": "Topic expression", - "client-scope": "Client scope", - "add-device": "Add device", - "opc-server": "Servers", - "opc-add-server": "Add server", - "opc-add-server-prompt": "Please add server", - "opc-application-name": "Application name", - "opc-application-uri": "Application uri", - "opc-scan-period-in-seconds": "Scan period in seconds", - "opc-security": "Security", - "opc-identity": "Identity", - "opc-keystore": "Keystore", - "opc-type": "Type", - "opc-keystore-type": "Type", - "opc-keystore-location": "Location *", - "opc-keystore-password": "Password", - "opc-keystore-alias": "Alias", - "opc-keystore-key-password": "Key password", - "opc-device-node-pattern": "Device node pattern", - "opc-device-name-pattern": "Device name pattern", - "modbus-server": "Servers/slaves", - "modbus-add-server": "Add server/slave", - "modbus-add-server-prompt": "Please add server/slave", - "modbus-transport": "Transport", - "modbus-port-name": "Serial port name", - "modbus-encoding": "Encoding", - "modbus-parity": "Parity", - "modbus-baudrate": "Baud rate", - "modbus-databits": "Data bits", - "modbus-stopbits": "Stop bits", - "modbus-databits-range": "Data bits should be in a range from 7 to 8.", - "modbus-stopbits-range": "Stop bits should be in a range from 1 to 2.", - "modbus-unit-id": "Unit ID", - "modbus-unit-id-range": "Unit ID should be in a range from 1 to 247.", - "modbus-device-name": "Device name", - "modbus-poll-period": "Poll period (ms)", - "modbus-attributes-poll-period": "Attributes poll period (ms)", - "modbus-timeseries-poll-period": "Timeseries poll period (ms)", - "modbus-poll-period-range": "Poll period should be positive value.", - "modbus-tag": "Tag", - "modbus-function": "Function", - "modbus-register-address": "Register address", - "modbus-register-address-range": "Register address should be in a range from 0 to 65535.", - "modbus-register-bit-index": "Bit index", - "modbus-register-bit-index-range": "Bit index should be in a range from 0 to 15.", - "modbus-register-count": "Register count", - "modbus-register-count-range": "Register count should be a positive value.", - "modbus-byte-order": "Byte order", + "ca-cert": "Файл CA сертификата *", + "private-key": "Файл приватного ключа *", + "cert": "Файл сертификата *", + "no-file": "Не выбран файл.", + "drop-file": "Перетяните файл или нажмите для выбора файла.", + "mapping": "Сопоставление", + "topic-filter": "Фильтр тем", + "converter-type": "Тип конвертера", + "converter-json": "JSON", + "json-name-expression": "JSON выражение для названия устройства", + "topic-name-expression": "Выражение для названия устройства в названии темы", + "json-type-expression": "JSON выражение для типа устройства", + "topic-type-expression": "Выражение для типа устройства в названии темы", + "attribute-key-expression": "Выражение для атрибута", + "attr-json-key-expression": "JSON выражение для атрибута", + "attr-topic-key-expression": "Выражение для атрибута в названии темы", + "request-id-expression": "Выражение для ИД запроса", + "request-id-json-expression": "JSON выражение для ИД запроса", + "request-id-topic-expression": "Выражение для ИД запроса в названии темы", + "response-topic-expression": "Выражение для темы ответов", + "value-expression": "Выражение для значения", + "topic": "Тема", + "timeout": "Таймаут в миллисекундах", + "converter-json-required": "JSON конвертер обязателен.", + "converter-json-parse": "Не удалось распознать JSON конвертера.", + "filter-expression": "Выражение для фильтрации", + "connect-requests": "Запросы о подключении устройства", + "add-connect-request": "Добавить запросы о подключении устройства", + "disconnect-requests": "Запросы об отсоединении устройства", + "add-disconnect-request": "Добавить запрос об отсоединении устройства", + "attribute-requests": "Запросы для атрибутов", + "add-attribute-request": "Добавить запрос для атрибутов", + "attribute-updates": "Обновление атрибутов", + "add-attribute-update": "Добавить обновление атрибутов", + "server-side-rpc": "Серверный RPC", + "add-server-side-rpc-request": "Добавить серверный RPC", + "device-name-filter": "Фильтр для названия устройства", + "attribute-filter": "Фильтр для атрибутов", + "method-filter": "Фильтр для процедур", + "request-topic-expression": "Выражение для темы запросов", + "response-timeout": "Время ожидания ответа в миллисекундах", + "topic-expression": "Выражение для названия темы", + "client-scope": "Клиентский", + "add-device": "Добавить устройство", + "opc-server": "Серверы", + "opc-add-server": "Добавить сервер", + "opc-add-server-prompt": "Пожалуйста, добавьте сервер", + "opc-application-name": "Название приложения", + "opc-application-uri": "URI приложения", + "opc-scan-period-in-seconds": "Частота сканирования в секундах", + "opc-security": "Безопасность", + "opc-identity": "Идентификация", + "opc-keystore": "Хранилище ключей", + "opc-type": "Тип", + "opc-keystore-type": "Тип", + "opc-keystore-location": "Расположение *", + "opc-keystore-password": "Пароль", + "opc-keystore-alias": "Псевдоним", + "opc-keystore-key-password": "Пароль для ключ", + "opc-device-node-pattern": "Паттерн OPC узла устройства", + "opc-device-name-pattern": "Паттерн названия устройства", + "modbus-server": "Серверы/ведомые устройства", + "modbus-add-server": "Добавить сервер/ведомое устройство", + "modbus-add-server-prompt": "Пожалуйста, добавить сервер/ведомое устройство", + "modbus-transport": "Транспорт", + "modbus-port-name": "Название последовательного порта", + "modbus-encoding": "Кодирование символов", + "modbus-parity": "Паритет", + "modbus-baudrate": "Скорость передачи", + "modbus-databits": "Биты данных", + "modbus-stopbits": "Стоп-биты", + "modbus-databits-range": "Параметр \"Биты данных\" может принимать значения 7 или 8.", + "modbus-stopbits-range": "Параметр \"Стоп-биты\" может принимать значения 1 или 2.", + "modbus-unit-id": "ИД устройства", + "modbus-unit-id-range": "ИД устройства должен быть в диапазоне от 1 до 247.", + "modbus-device-name": "Название устройства", + "modbus-poll-period": "Частота опроса (в миллисекундах)", + "modbus-attributes-poll-period": "Частота опроса для атрибутов (в миллисекундах)", + "modbus-timeseries-poll-period": "Частота опроса для телеметрии (в миллисекундах)", + "modbus-poll-period-range": "Значение параметра \"Частота опроса\" должно быть больше ноля.", + "modbus-tag": "Тег", + "modbus-function": "Modbus функция", + "modbus-register-address": "Адрес регистра", + "modbus-register-address-range": "Адрес регистра должен быть в диапазоне от 0 до 65535.", + "modbus-register-bit-index": "Номер бита", + "modbus-register-bit-index-range": "Номер бита должен быть в диапазоне от 0 до 15.", + "modbus-register-count": "Количество регистров", + "modbus-register-count-range": "Количество регистров должно быть больше ноля.", + "modbus-byte-order": "Порядок байтов", "sync": { - "status": "Status", - "sync": "Sync", - "not-sync": "Not sync", - "last-sync-time": "Last sync time", - "not-available": "Not available" + "status": "Статус", + "sync": "Синхронизирован", + "not-sync": "Не синхронизирован", + "last-sync-time": "Время последней синхронизации", + "not-available": "Не доступен" }, - "export-extensions-configuration": "Export extensions configuration", - "import-extensions-configuration": "Import extensions configuration", - "import-extensions": "Import extensions", - "import-extension": "Import extension", - "export-extension": "Export extension", - "file": "Extensions file", - "invalid-file-error": "Invalid extension file" + "export-extensions-configuration": "Экспортировать конфигурацию расширений", + "import-extensions-configuration": "Импортировать конфигурацию расширений", + "import-extensions": "Импортировать расширения", + "import-extension": "Импортировать расширение", + "export-extension": "Экспортировать расширение", + "file": "Файл расширений", + "invalid-file-error": "Не правильный формат файла" }, "fullscreen": { "expand": "Во весь экран", @@ -937,20 +1095,20 @@ "tidy": "Tidy" }, "key-val": { - "key": "Key", - "value": "Value", - "remove-entry": "Remove entry", - "add-entry": "Add entry", - "no-data": "No entries" + "key": "Ключ", + "value": "Значение", + "remove-entry": "Удалить элемент", + "add-entry": "Добавить элемент", + "no-data": "Элементы отсутствуют" }, "layout": { - "layout": "Layout", - "manage": "Manage layouts", - "settings": "Layout settings", - "color": "Color", - "main": "Main", - "right": "Right", - "select": "Select target layout" + "layout": "Макет", + "manage": "Управление макетами", + "settings": "Настройки макета", + "color": "Цвет", + "main": "Основной", + "right": "Правый", + "select": "Выбрать макет" }, "legend": { "position": "Расположение легенды", @@ -993,140 +1151,149 @@ "current-password": "Текущий пароль" }, "relation": { - "relations": "Relations", - "direction": "Direction", + "relations": "Отношения", + "direction": "Направления", "search-direction": { - "FROM": "From", - "TO": "To" + "FROM": "От", + "TO": "К" }, "direction-type": { - "FROM": "from", - "TO": "to" + "FROM": "от", + "TO": "к" }, - "from-relations": "Outbound relations", - "to-relations": "Inbound relations", - "selected-relations": "{ count, plural, 1 {1 relation} other {# relations} } selected", - "type": "Type", - "to-entity-type": "To entity type", - "to-entity-name": "To entity name", - "from-entity-type": "From entity type", - "from-entity-name": "From entity name", - "to-entity": "To entity", - "from-entity": "From entity", - "delete": "Delete relation", - "relation-type": "Relation type", - "relation-type-required": "Relation type is required.", - "any-relation-type": "Any type", - "add": "Add relation", - "edit": "Edit relation", - "delete-to-relation-title": "Are you sure you want to delete relation to the entity '{{entityName}}'?", - "delete-to-relation-text": "Be careful, after the confirmation the entity '{{entityName}}' will be unrelated from the current entity.", - "delete-to-relations-title": "Are you sure you want to delete { count, plural, 1 {1 relation} other {# relations} }?", - "delete-to-relations-text": "Be careful, after the confirmation all selected relations will be removed and corresponding entities will be unrelated from the current entity.", - "delete-from-relation-title": "Are you sure you want to delete relation from the entity '{{entityName}}'?", - "delete-from-relation-text": "Be careful, after the confirmation current entity will be unrelated from the entity '{{entityName}}'.", - "delete-from-relations-title": "Are you sure you want to delete { count, plural, 1 {1 relation} other {# relations} }?", - "delete-from-relations-text": "Be careful, after the confirmation all selected relations will be removed and current entity will be unrelated from the corresponding entities.", - "remove-relation-filter": "Remove relation filter", - "add-relation-filter": "Add relation filter", - "any-relation": "Any relation", - "relation-filters": "Relation filters", - "additional-info": "Additional info (JSON)", - "invalid-additional-info": "Unable to parse additional info json." + "from-relations": "Исходящие отношения", + "to-relations": "Входящие отношения", + "selected-relations": "Выбрано { count, plural, 1 {1 отношение} few {# отношения} other {# отношений} }", + "type": "Тип", + "to-entity-type": "К типу объекта", + "to-entity-name": "К объекта", + "from-entity-type": "От типа объекта", + "from-entity-name": "От объекта", + "to-entity": "К объекту", + "from-entity": "От объекта", + "delete": "Удалить отношение", + "relation-type": "Тип отношения", + "relation-type-required": "Тип отношения обязателен.", + "any-relation-type": "Любой тип", + "add": "Добавить отношение", + "edit": "Редактировать отношение", + "delete-to-relation-title": "Вы точно хотите удалить отношение, идущее к объекту '{{entityName}}'?", + "delete-to-relation-text": "Внимание, после подтверждения объект '{{entityName}}' будет отвязан от текущего объекта.", + "delete-to-relations-title": "Вы точно хотите удалить { count, plural, 1 {1 отношение} few {# отношения} other {# отношений} }?", + "delete-to-relations-text": "Внимание, после подтверждения выбранные объекты будут отвязаны от текущего объекта.", + "delete-from-relation-title": "Вы точно хотите удалить отношение, идущее от объекта '{{entityName}}'?", + "delete-from-relation-text": "Внимание, после подтверждения текущий объект будет отвязан от объекта '{{entityName}}'.", + "delete-from-relations-title": "Вы точно хотите удалить { count, plural, 1 {1 отношение} few {# отношения} other {# отношений} }?", + "delete-from-relations-text": "Внимание, после подтверждения выбранные объекты будут отвязаны от соответствующих объектов.", + "remove-relation-filter": "Удалить фильтр отношений", + "add-relation-filter": "Добавить фильтр отношений", + "any-relation": "Любое отношение", + "relation-filters": "Фильтры отношений", + "additional-info": "Дополнительная информация (JSON)", + "invalid-additional-info": "Не удалось распознать JSON с дополнительной информацией." }, "rulechain": { - "rulechain": "Rule chain", - "rulechains": "Rule chains", - "root": "Root", - "delete": "Delete rule chain", - "name": "Name", - "name-required": "Name is required.", - "description": "Description", - "add": "Add Rule Chain", - "set-root": "Make rule chain root", - "set-root-rulechain-title": "Are you sure you want to make the rule chain '{{ruleChainName}}' root?", - "set-root-rulechain-text": "After the confirmation the rule chain will become root and will handle all incoming transport messages.", - "delete-rulechain-title": "Are you sure you want to delete the rule chain '{{ruleChainName}}'?", - "delete-rulechain-text": "Be careful, after the confirmation the rule chain and all related data will become unrecoverable.", - "delete-rulechains-title": "Are you sure you want to delete { count, plural, 1 {1 rule chain} other {# rule chains} }?", - "delete-rulechains-action-title": "Delete { count, plural, 1 {1 rule chain} other {# rule chains} }", - "delete-rulechains-text": "Be careful, after the confirmation all selected rule chains will be removed and all related data will become unrecoverable.", - "add-rulechain-text": "Add new rule chain", - "no-rulechains-text": "No rule chains found", - "rulechain-details": "Rule chain details", - "details": "Details", - "events": "Events", - "system": "System", - "import": "Import rule chain", - "export": "Export rule chain", - "export-failed-error": "Unable to export rule chain: {{error}}", - "create-new-rulechain": "Create new rule chain", - "rulechain-file": "Rule chain file", - "invalid-rulechain-file-error": "Unable to import rule chain: Invalid rule chain data structure.", - "copyId": "Copy rule chain Id", - "idCopiedMessage": "Rule chain Id has been copied to clipboard", - "select-rulechain": "Select rule chain", - "no-rulechains-matching": "No rule chains matching '{{entity}}' were found.", - "rulechain-required": "Rule chain is required", - "management": "Rules management", - "debug-mode": "Debug mode" + "rulechain": "Цепочка правил", + "rulechains": "Цепочки правил", + "root": "Корневая", + "delete": "Удалить цепочку правил", + "name": "Названия", + "name-required": "Название необходимо.", + "description": "Описание", + "add": "Добавить цепочку правил", + "set-root": "Сделать цепочку корневой", + "set-root-rulechain-title": "Вы точно хотите сделать цепочку правил '{{ruleChainName}}' корневой?", + "set-root-rulechain-text": "После подтверждения цепочка правил станет корневой и будет обрабатывать все входящие сообщения.", + "delete-rulechain-title": "Вы точно хотите удалить цепочку правил '{{ruleChainName}}'?", + "delete-rulechain-text": "Внимание, после подтверждения цепочка правил и все связанные с ней данные будут безвозвратно удалены.", + "delete-rulechains-title": "Вы точно хотите удалить { count, plural, 1 {1 цепочку правил} few {# цепочки правил} other {# цепочек правил} }?", + "delete-rulechains-action-title": "Удалить { count, plural, 1 {1 цепочку правил} few {# цепочки правил} other {# цепочек правил} }", + "delete-rulechains-text": "Внимание, после подтверждения выбранные цепочки правил и все связанные с ними данные будут безвозвратно удалены.", + "add-rulechain-text": "Добавить новую цепочку правил", + "no-rulechains-text": "Цепочки правил не найдены", + "rulechain-details": "Подробности о цепочке правил", + "details": "Подробности", + "events": "События", + "system": "Системная", + "import": "Импортировать цепочку правил", + "export": "Экспортировать цепочку правил", + "export-failed-error": "Не удалось экспортировать цепочку правил: {{error}}", + "create-new-rulechain": "Создать новую цепочку правил", + "rulechain-file": "Файл цепочки правил", + "invalid-rulechain-file-error": "Не удалось импортировать цепочку правил: неправильный формат.", + "copyId": "Копировать ИД цепочки правил", + "idCopiedMessage": "ИД цепочки правил скопирован в буфер обмена", + "select-rulechain": "Выбрать цепочку правил", + "no-rulechains-matching": "Цепочки правил, соответствующие '{{entity}}', не найдены.", + "rulechain-required": "Цепочка правил обязательна", + "management": "Управление цепочками правил", + "debug-mode": "Режим отладки" }, "rulenode": { - "details": "Details", - "events": "Events", - "search": "Search nodes", - "open-node-library": "Open node library", - "add": "Add rule node", - "name": "Name", - "name-required": "Name is required.", - "type": "Type", - "description": "Description", - "delete": "Delete rule node", - "select-all-objects": "Select all nodes and connections", - "deselect-all-objects": "Deselect all nodes and connections", - "delete-selected-objects": "Delete selected nodes and connections", - "delete-selected": "Delete selected", - "select-all": "Select all", - "copy-selected": "Copy selected", - "deselect-all": "Deselect all", - "rulenode-details": "Rule node details", - "debug-mode": "Debug mode", - "configuration": "Configuration", - "link": "Link", - "link-details": "Rule node link details", - "add-link": "Add link", - "link-label": "Link label", - "link-label-required": "Link label is required.", - "custom-link-label": "Custom link label", - "custom-link-label-required": "Custom link label is required.", - "type-filter": "Filter", - "type-filter-details": "Filter incoming messages with configured conditions", - "type-enrichment": "Enrichment", - "type-enrichment-details": "Add additional information into Message Metadata", - "type-transformation": "Transformation", - "type-transformation-details": "Change Message payload and Metadata", - "type-action": "Action", - "type-action-details": "Perform special action", - "type-external": "External", - "type-external-details": "Interacts with external system", - "type-rule-chain": "Rule Chain", - "type-rule-chain-details": "Forwards incoming messages to specified Rule Chain", - "type-input": "Input", - "type-input-details": "Logical input of Rule Chain, forwards incoming messages to next related Rule Node", - "directive-is-not-loaded": "Defined configuration directive '{{directiveName}}' is not available.", - "ui-resources-load-error": "Failed to load configuration ui resources.", - "invalid-target-rulechain": "Unable to resolve target rule chain!", - "test-script-function": "Test script function", - "message": "Message", - "message-type": "Message type", - "message-type-required": "Message type is required", - "metadata": "Metadata", - "metadata-required": "Metadata entries can't be empty.", - "output": "Output", - "test": "Test", - "help": "Help" + "details": "Подробности", + "events": "События", + "search": "Поиск правил", + "open-node-library": "Открыть библиотеку правил", + "add": "Добавить правило", + "name": "Название", + "name-required": "Название обязательно.", + "type": "Тип", + "description": "Описание", + "delete": "Удалить правило", + "select-all-objects": "Выделить все правила и связи", + "deselect-all-objects": "Отменить выделение правил и связей", + "delete-selected-objects": "Удалить выделенные правила и связи", + "delete-selected": "Удалить выделенные", + "select-all": "Выделить всё", + "copy-selected": "Копировать выделенное", + "deselect-all": "Отменить выделение", + "rulenode-details": "Подробности о правиле", + "debug-mode": "Режим отладки", + "configuration": "Настройки", + "link": "Связь", + "link-details": "Подробности о связи правила", + "add-link": "Добавить связь", + "link-label": "Метка связи", + "link-label-required": "Метка связи обязателен.", + "custom-link-label": "Пользовательская метка связи", + "custom-link-label-required": "Пользовательская метка связи обязателен.", + "link-labels": "Метки связи", + "link-labels-required": "Метки связи обязательны.", + "no-link-labels-found": "Метки связи не найдены", + "no-link-label-matching": "Метка '{{label}}' не найдена.", + "create-new-link-label": "Создать новую!", + "type-filter": "Фильтр", + "type-filter-details": "Фильтр входящих сообщений с заданными условиями", + "type-enrichment": "Насыщение", + "type-enrichment-details": "Добавить данные в метадату сообщения", + "type-transformation": "Преобразование", + "type-transformation-details": "Изменить содержимое сообщение и его метадату", + "type-action": "Действие", + "type-action-details": "Выполнить заданное действие", + "type-external": "Сторонние", + "type-external-details": "Взаимодействовать со сторонними системами", + "type-rule-chain": "Цепочка правил", + "type-rule-chain-details": "Перенаправить входящее сообщение в другую цепочку правил", + "type-input": "Вход", + "type-input-details": "Логический вход цепочки правил перенаправляет входящие сообщения в следующее правило", + "type-unknown": "Неизвестный", + "type-unknown-details": "Неопределенное правило", + "directive-is-not-loaded": "Указанная директива конфигурации '{{directiveName}}' не доступна.", + "ui-resources-load-error": "Не удалось загрузить UI ресурсы.", + "invalid-target-rulechain": "Не удалось определить целевую цепочку правил!", + "test-script-function": "Протестировать скрипт", + "message": "Сообщение", + "message-type": "Тип сообщения", + "select-message-type": "Выбрать тип сообщения", + "message-type-required": "Тип сообщения обязателен", + "metadata": "Метаданные", + "metadata-required": "Метаданные объекта не могут быть пустыми.", + "output": "Выход", + "test": "Протестировать", + "help": "Помощь" }, "tenant": { + "tenant": "Владелец", "tenants": "Владельцы", "management": "Управление владельцами", "add": "Добавить владельца", @@ -1144,6 +1311,13 @@ "title": "Имя", "title-required": "Имя обязательно.", "description": "Описание" + "details": "Подробности", + "events": "События", + "copyId": "Копировать ИД владельца", + "idCopiedMessage": "ИД владельца скопирован в буфер обмена", + "select-tenant": "Выбрать владельца", + "no-tenants-matching": "Владельцы, соответствующие '{{entity}}', не найдены.", + "tenant-required": "Владелец обязателен" }, "timeinterval": { "seconds-interval": "{ seconds, plural, one {1 секунда} few {# секунды} other {# секунд} }", @@ -1171,6 +1345,7 @@ "time-period": "Период времени" }, "user": { + "user": "Пользователь", "users": "Пользователи", "customer-users": "Пользователи клиента", "tenant-admins": "Администраторы владельца", @@ -1192,11 +1367,25 @@ "resend-activation": "Повторить отправку активационного письма", "email": "Эл. адрес", "email-required": "Эл. адрес обязателен.", + "invalid-email-format": "Не правильный формат письма.", "first-name": "Имя", "last-name": "Фамилия", "description": "Описание", "default-dashboard": "Дашборд по умолчанию", - "always-fullscreen": "Всегда во весь экран" + "always-fullscreen": "Всегда в полноэкранном режиме", + "select-user": "Выбрать пользователя", + "no-users-matching": "Пользователи, соответствующие '{{entity}}', не найдены.", + "user-required": "Пользователь обязателен", + "activation-method": "Метод активации", + "display-activation-link": "Отобразить ссылку для активации", + "send-activation-mail": "Отправить активационное письмо", + "activation-link": "Активационная ссылка для пользователя", + "activation-link-text": "Для активации пользователя используйте ссылку :", + "copy-activation-link": "Копировать активационную ссылку", + "activation-link-copied-message": "Ссылка для активации пользователя скопировано в буфер обмена", + "details": "Подробности", + "login-as-tenant-admin": "Войти как администратор владельца", + "login-as-customer-user": "Войти как пользователь клиента" }, "value": { "type": "Тип значения", @@ -1210,7 +1399,8 @@ "boolean": "Логический тип", "boolean-value": "Логическое значение", "false": "Ложь", - "true": "Правда" + "true": "Правда", + "long": "Целое число" }, "widget": { "widget-library": "Галерея виджетов", @@ -1225,8 +1415,11 @@ "remove-widget-title": "Вы точно хотите удалить виджет '{{widgetTitle}}'?", "remove-widget-text": "Внимание, после подтверждения виджет и все связанные с ним данные будут безвозвратно утеряны.", "timeseries": "Выборка по времени", + "search-data": "Search data", + "no-data-found": "No data found", "latest-values": "Последние значения", "rpc": "Управляющий виджет", + "alarm": "Alarm widget", "static": "Статический виджет", "select-widget-type": "Выберите тип виджета", "missing-widget-title-error": "Укажите название виджета!", @@ -1262,16 +1455,16 @@ "export": "Экспортировать виджет" }, "widget-action": { - "header-button": "Widget header button", - "open-dashboard-state": "Navigate to new dashboard state", - "update-dashboard-state": "Update current dashboard state", - "open-dashboard": "Navigate to other dashboard", - "custom": "Custom action", - "target-dashboard-state": "Target dashboard state", - "target-dashboard-state-required": "Target dashboard state is required", - "set-entity-from-widget": "Set entity from widget", - "target-dashboard": "Target dashboard", - "open-right-layout": "Open right dashboard layout (mobile view)" + "header-button": "Кнопка заголовка виджета", + "open-dashboard-state": "Перейти к новомум состоянию дашборда", + "update-dashboard-state": "Обновить текущее состояние дашборда", + "open-dashboard": "Перейти к другому дашборду", + "custom": "Пользовательское действие", + "target-dashboard-state": "Целевое состояние дашборда", + "target-dashboard-state-required": "Целевое состояние дашборда обязательно", + "set-entity-from-widget": "Установить объект из виджета", + "target-dashboard": "Целевой дашборд", + "open-right-layout": "Открыть мобильный режим дашборда" }, "widgets-bundle": { "current": "Текущий набор", @@ -1312,6 +1505,8 @@ "background-color": "Цвет фона", "text-color": "Цвет текста", "padding": "Отступ", + "margin": "Margin", + "widget-style": "Стиль виджета", "title-style": "Стиль названия", "mobile-mode-settings": "Настройки мобильного режима", "order": "Порядок", @@ -1322,11 +1517,29 @@ "use-dashboard-timewindow": "Использовать временное окно дашборда", "display-legend": "Показать легенду", "datasources": "Источники данных", + "maximum-datasources": "Максимальной количество источников данных равно {{count}}", "datasource-type": "Тип", "datasource-parameters": "Параметры", "remove-datasource": "Удалить источник данных", "add-datasource": "Добавить источник данных", "target-device": "Целевое устройство" + "alarm-source": "Источник оповещения", + "actions": "Действия", + "action": "Действие", + "add-action": "Добавить действие", + "search-actions": "Поиск действий", + "action-source": "Источник действий", + "action-source-required": "Источник действий обязателен.", + "action-name": "Название", + "action-name-required": "Название действия обязательно.", + "action-name-not-unique": "Действие с таким именем уже существует.
Название должно быть уникально в рамках одного источника действий.", + "action-icon": "Иконка", + "action-type": "Тип", + "action-type-required": "Тип действий обязателен.", + "edit-action": "Редактировать действие", + "delete-action": "Удалить действие", + "delete-action-title": "Удалить действие виджета", + "delete-action-text": "Вы точно хотите удалить действие виджета '{{actionName}}'?" }, "widget-type": { "import": "Импортировать тип виджета", @@ -1337,32 +1550,31 @@ "invalid-widget-type-file-error": "Не удалось импортировать виджет: неизвестная схема данных типа виджета." }, "icon": { - "icon": "Icon", - "select-icon": "Select icon", - "material-icons": "Material icons", - "show-all": "Show all icons" + "icon": "Иконка", + "select-icon": "Выбрать иконку", + "material-icons": "Иконки в стиле Material", + "show-all": "Показать все иконки" }, "custom": { "widget-action": { - "action-cell-button": "Action cell button", - "row-click": "On row click", - "marker-click": "On marker click", - "tooltip-tag-action": "Tooltip tag action" + "action-cell-button": "Кнопка действия ячейки", + "row-click": "Действий при щелчке на строку", + "marker-click": "Действия при щелчке на указателе", + "tooltip-tag-action": "Действие при подсказке" } }, "language": { "language": "Язык", "locales": { "en_US": "Английский", - "fr_FR": "Французский", "zh_CN": "Китайский", "ko_KR": "Корейский", "es_ES": "Испанский", "it_IT": "Итальянский", "ru_RU": "Русский", - "ja_JA": "Японский", - "tr_TR": "Турецкий" + "tr_TR": "Турецкий", + "fr_FR": "Французский", + "ja_JA": "Японский" } - } } From 8e590a52945ff86857697bfa5a278d280bc483a7 Mon Sep 17 00:00:00 2001 From: dvk2018 Date: Tue, 25 Dec 2018 17:19:48 +0500 Subject: [PATCH 12/27] Add missing commas in JSON. --- ui/src/app/locale/locale.constant-ru_RU.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/app/locale/locale.constant-ru_RU.json b/ui/src/app/locale/locale.constant-ru_RU.json index 07ae86e5a0..3c6126ebfd 100644 --- a/ui/src/app/locale/locale.constant-ru_RU.json +++ b/ui/src/app/locale/locale.constant-ru_RU.json @@ -555,7 +555,7 @@ "alarm-fields-required": "Параметры оповещения обязательны.", "function-types": "Тип функции", "function-types-required": "Тип функции обязателен.", - "maximum-function-types": "Максимальное количество типов функции равно {{count}}" + "maximum-function-types": "Максимальное количество типов функции равно {{count}}", "time-description": "время текущего значения;", "value-description": "текущее значение;", "prev-value-description": "результат предыдущего вызова функции;", @@ -664,7 +664,7 @@ "unable-delete-device-alias-text": "Не удалось удалить псевдоним '{{deviceAlias}}' устройства, т.к. он используется следующими виджетами:
{{widgetsList}}", "is-gateway": "Гейтвей", "public": "Общедоступный", - "device-public": "Устройство общедоступно" + "device-public": "Устройство общедоступно", "select-device": "Выбрать устройство" }, "dialog": { @@ -1310,7 +1310,7 @@ "delete-tenants-text": "Внимание, после подтверждения выбранные Владельцы и все связанные с ними данные будут безвозвратно утеряны.", "title": "Имя", "title-required": "Имя обязательно.", - "description": "Описание" + "description": "Описание", "details": "Подробности", "events": "События", "copyId": "Копировать ИД владельца", @@ -1522,7 +1522,7 @@ "datasource-parameters": "Параметры", "remove-datasource": "Удалить источник данных", "add-datasource": "Добавить источник данных", - "target-device": "Целевое устройство" + "target-device": "Целевое устройство", "alarm-source": "Источник оповещения", "actions": "Действия", "action": "Действие", From 0686d3a21b38f459efe0094b965cfff2b95c4345 Mon Sep 17 00:00:00 2001 From: nordmif Date: Tue, 11 Dec 2018 20:11:12 +0200 Subject: [PATCH 13/27] fixed conflicts --- .../server/controller/TelemetryController.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index bebd2cc4d3..4748c22e25 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -279,8 +279,14 @@ public class TelemetryController extends BaseController { deleteFromTs = 0L; deleteToTs = System.currentTimeMillis(); } else { - deleteFromTs = startTs; - deleteToTs = endTs; + if (startTs == null || endTs == null) { + deleteToTs = endTs; + return getImmediateDeferredResult("When deleteAllDataForKeys is false, start and end timestamp values shouldn't be empty", HttpStatus.BAD_REQUEST); + } + else{ + deleteFromTs = startTs; + deleteToTs = endTs; + } } return accessValidator.validateEntityAndCallback(user, entityIdStr, (result, tenantId, entityId) -> { From 9590c37720ac9c7c175a90e6450053a941da7940 Mon Sep 17 00:00:00 2001 From: dvk2018 Date: Sat, 8 Dec 2018 17:35:13 +0500 Subject: [PATCH 14/27] Add 'Reconnect' and 'RTU over TCP' options to TCP Modbus extension configuration. --- .../extension-form-modbus.directive.js | 45 ++++++-- .../extension-form-modbus.tpl.html | 104 +++++++++++------- ui/src/app/locale/locale.constant-en_US.json | 2 + 3 files changed, 99 insertions(+), 52 deletions(-) diff --git a/ui/src/app/extension/extensions-forms/extension-form-modbus.directive.js b/ui/src/app/extension/extensions-forms/extension-form-modbus.directive.js index 2dfc961d02..96c398b897 100644 --- a/ui/src/app/extension/extensions-forms/extension-form-modbus.directive.js +++ b/ui/src/app/extension/extensions-forms/extension-form-modbus.directive.js @@ -31,17 +31,38 @@ export default function ExtensionFormModbusDirective($compile, $templateCache, $ var linker = function(scope, element) { + function TcpTransport() { + this.type = "tcp", + this.host = "localhost", + this.port = 502, + this.timeout = 5000, + this.reconnect = true, + this.rtuOverTcp = false + } + + function UdpTransport() { + this.type = "udp", + this.host = "localhost", + this.port = 502, + this.timeout = 5000 + } + + function RtuTransport() { + this.type = "rtu", + this.portName = "COM1", + this.encoding = "ascii", + this.timeout = 5000, + this.baudRate = 115200, + this.dataBits = 7, + this.stopBits = 1, + this.parity ="even" + } function Server() { - this.transport = { - "type": "tcp", - "host": "localhost", - "port": 502, - "timeout": 3000 - }; + this.transport = new TcpTransport(); this.devices = [] } - + function Device() { this.unitId = 1; this.deviceName = ""; @@ -105,9 +126,13 @@ export default function ExtensionFormModbusDirective($compile, $templateCache, $ scope.onTransportChanged = function(server) { var type = server.transport.type; - server.transport = {}; - server.transport.type = type; - server.transport.timeout = 3000; + if (type === "tcp") { + server.transport = new TcpTransport(); + } else if (type === "udp") { + server.transport = new UdpTransport(); + } else if (type === "rtu") { + server.transport = new RtuTransport(); + } scope.theForm.$setDirty(); }; diff --git a/ui/src/app/extension/extensions-forms/extension-form-modbus.tpl.html b/ui/src/app/extension/extensions-forms/extension-form-modbus.tpl.html index 989d3f07db..508ddc0c42 100644 --- a/ui/src/app/extension/extensions-forms/extension-form-modbus.tpl.html +++ b/ui/src/app/extension/extensions-forms/extension-form-modbus.tpl.html @@ -73,49 +73,69 @@ -
- - - -
-
extension.field-required
-
-
+
+
+ + + +
+
extension.field-required
+
+
- - - -
-
extension.field-required
-
extension.port-range
-
extension.port-range
-
-
- - - - -
-
extension.field-required
-
-
+ + + +
+
extension.field-required
+
extension.port-range
+
extension.port-range
+
+
+ + + + +
+
extension.field-required
+
+
+
+ +
+ + {{ 'extension.modbus-tcp-reconnect' | translate }} + + + + + {{ 'extension.modbus-rtu-over-tcp' | translate }} + + +
diff --git a/ui/src/app/locale/locale.constant-en_US.json b/ui/src/app/locale/locale.constant-en_US.json index 30e1eb119b..3aa520a955 100644 --- a/ui/src/app/locale/locale.constant-en_US.json +++ b/ui/src/app/locale/locale.constant-en_US.json @@ -1008,6 +1008,8 @@ "modbus-add-server": "Add server/slave", "modbus-add-server-prompt": "Please add server/slave", "modbus-transport": "Transport", + "modbus-tcp-reconnect": "Automatically reconnect", + "modbus-rtu-over-tcp": "RTU over TCP", "modbus-port-name": "Serial port name", "modbus-encoding": "Encoding", "modbus-parity": "Parity", From f5bd9a2133e4c442a054e620e774c141ff55cac3 Mon Sep 17 00:00:00 2001 From: Andrew Shvayka Date: Thu, 27 Dec 2018 13:11:47 +0200 Subject: [PATCH 15/27] Issue #1327 fixed --- .../thingsboard/server/transport/mqtt/MqttTransportHandler.java | 1 + .../src/main/java/org/thingsboard/mqtt/MqttClientCallback.java | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index 3986837f6f..1a759bc98c 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -271,6 +271,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement case MqttTopics.DEVICE_RPC_RESPONSE_SUB_TOPIC: case MqttTopics.GATEWAY_ATTRIBUTES_TOPIC: case MqttTopics.GATEWAY_RPC_TOPIC: + case MqttTopics.GATEWAY_ATTRIBUTES_RESPONSE_TOPIC: case MqttTopics.DEVICE_ATTRIBUTES_RESPONSES_TOPIC: registerSubQoS(topic, grantedQoSList, reqQoS); break; diff --git a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientCallback.java b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientCallback.java index 9f86b8e6cd..000925e8b4 100644 --- a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientCallback.java +++ b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttClientCallback.java @@ -15,8 +15,6 @@ */ package org.thingsboard.mqtt; -import io.netty.channel.ChannelId; - /** * Created by Valerii Sosliuk on 12/30/2017. */ From d6eb5727794f3265c313be628837734fc683c2ce Mon Sep 17 00:00:00 2001 From: Volodymyr Babak Date: Wed, 26 Dec 2018 20:46:03 +0200 Subject: [PATCH 16/27] Improved logging for bound statement --- .../util/AbstractBufferedRateExecutor.java | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java index a5415f0a1c..8a70059bb2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java +++ b/dao/src/main/java/org/thingsboard/server/dao/util/AbstractBufferedRateExecutor.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.util; +import com.datastax.driver.core.*; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -22,6 +23,7 @@ import com.google.common.util.concurrent.SettableFuture; import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.msg.tools.TbRateLimits; +import org.thingsboard.server.dao.nosql.CassandraStatementTask; import javax.annotation.Nullable; import java.util.UUID; @@ -183,12 +185,39 @@ public abstract class AbstractBufferedRateExecutor taskCtx) { if (log.isTraceEnabled()) { - log.trace("[{}] {} task: {}", taskCtx.getId(), action, taskCtx); + if (taskCtx.getTask() instanceof CassandraStatementTask) { + CassandraStatementTask cassStmtTask = (CassandraStatementTask) taskCtx.getTask(); + if (cassStmtTask.getStatement() instanceof BoundStatement) { + BoundStatement stmt = (BoundStatement) cassStmtTask.getStatement(); + String query = toStringWithValues(stmt, ProtocolVersion.V5); + log.trace("[{}] {} task: {}, BoundStatement query: {}", taskCtx.getId(), action, taskCtx, query); + } + } else { + log.trace("[{}] {} task: {}", taskCtx.getId(), action, taskCtx); + } } else { log.debug("[{}] {} task", taskCtx.getId(), action); } } + private static String toStringWithValues(BoundStatement boundStatement, ProtocolVersion protocolVersion) { + CodecRegistry codecRegistry = boundStatement.preparedStatement().getCodecRegistry(); + PreparedStatement preparedStatement = boundStatement.preparedStatement(); + String query = preparedStatement.getQueryString(); + ColumnDefinitions defs = preparedStatement.getVariables(); + int index = 0; + for (ColumnDefinitions.Definition def : defs) { + DataType type = def.getType(); + TypeCodec codec = codecRegistry.codecFor(type); + if (boundStatement.getBytesUnsafe(index) != null) { + Object value = codec.deserialize(boundStatement.getBytesUnsafe(index), protocolVersion); + query = query.replaceFirst("\\?", codec.format(value)); + } + index++; + } + return query; + } + protected int getQueueSize() { return queue.size(); } From 920ebc792a1df4f89d7f78215a43994e5128f405 Mon Sep 17 00:00:00 2001 From: Andrew Shvayka Date: Thu, 27 Dec 2018 14:02:03 +0200 Subject: [PATCH 17/27] Issue #1355 fixed --- .../service/transport/LocalTransportApiService.java | 6 +++--- .../transport/mqtt/MqttSslHandlerProvider.java | 12 ++++++------ .../mqtt/MqttTransportServerInitializer.java | 3 +-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java index 7436de8b72..9366c7e150 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java @@ -100,7 +100,7 @@ public class LocalTransportApiService implements TransportApiService { //TODO: Make async and enable caching DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByCredentialsId(credentialsId); if (credentials != null && credentials.getCredentialsType() == credentialsType) { - return getDeviceInfo(credentials.getDeviceId()); + return getDeviceInfo(credentials.getDeviceId(), credentials); } else { return getEmptyTransportApiResponseFuture(); } @@ -135,7 +135,7 @@ public class LocalTransportApiService implements TransportApiService { } - private ListenableFuture getDeviceInfo(DeviceId deviceId) { + private ListenableFuture getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) { return Futures.transform(deviceService.findDeviceByIdAsync(TenantId.SYS_TENANT_ID, deviceId), device -> { if (device == null) { log.trace("[{}] Failed to lookup device by id", deviceId); @@ -143,7 +143,7 @@ public class LocalTransportApiService implements TransportApiService { } try { return TransportApiResponseMsg.newBuilder() - .setValidateTokenResponseMsg(ValidateDeviceCredentialsResponseMsg.newBuilder().setDeviceInfo(getDeviceInfoProto(device)).build()).build(); + .setValidateTokenResponseMsg(ValidateDeviceCredentialsResponseMsg.newBuilder().setDeviceInfo(getDeviceInfoProto(device)).setCredentialsBody(credentials.getCredentialsValue()).build()).build(); } catch (JsonProcessingException e) { log.warn("[{}] Failed to lookup device by id", deviceId, e); return getEmptyTransportApiResponse(); diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java index aa643ebc9b..29e5859aea 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttSslHandlerProvider.java @@ -54,18 +54,18 @@ import java.util.concurrent.TimeUnit; @Slf4j @Component("MqttSslHandlerProvider") @ConditionalOnExpression("'${transport.type:null}'=='null' || ('${transport.type}'=='local' && '${transport.http.enabled}'=='true')") -@ConditionalOnProperty(prefix = "mqtt.ssl", value = "enabled", havingValue = "true", matchIfMissing = false) +@ConditionalOnProperty(prefix = "transport.mqtt.ssl", value = "enabled", havingValue = "true", matchIfMissing = false) public class MqttSslHandlerProvider { - @Value("${mqtt.ssl.protocol}") + @Value("${transport.mqtt.ssl.protocol}") private String sslProtocol; - @Value("${mqtt.ssl.key_store}") + @Value("${transport.mqtt.ssl.key_store}") private String keyStoreFile; - @Value("${mqtt.ssl.key_store_password}") + @Value("${transport.mqtt.ssl.key_store_password}") private String keyStorePassword; - @Value("${mqtt.ssl.key_password}") + @Value("${transport.mqtt.ssl.key_password}") private String keyPassword; - @Value("${mqtt.ssl.key_store_type}") + @Value("${transport.mqtt.ssl.key_store_type}") private String keyStoreType; @Autowired diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportServerInitializer.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportServerInitializer.java index 550837842f..eb8e5fb60f 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportServerInitializer.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportServerInitializer.java @@ -36,9 +36,8 @@ public class MqttTransportServerInitializer extends ChannelInitializer Date: Fri, 28 Dec 2018 11:19:06 +0200 Subject: [PATCH 18/27] Build fix --- .../service/transport/LocalTransportApiService.java | 8 +++++++- .../transport/service/AbstractTransportService.java | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java b/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java index 9366c7e150..2ad5e37369 100644 --- a/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java +++ b/application/src/main/java/org/thingsboard/server/service/transport/LocalTransportApiService.java @@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; @@ -142,8 +143,13 @@ public class LocalTransportApiService implements TransportApiService { return getEmptyTransportApiResponse(); } try { + ValidateDeviceCredentialsResponseMsg.Builder builder = ValidateDeviceCredentialsResponseMsg.newBuilder(); + builder.setDeviceInfo(getDeviceInfoProto(device)); + if(!StringUtils.isEmpty(credentials.getCredentialsValue())){ + builder.setCredentialsBody(credentials.getCredentialsValue()); + } return TransportApiResponseMsg.newBuilder() - .setValidateTokenResponseMsg(ValidateDeviceCredentialsResponseMsg.newBuilder().setDeviceInfo(getDeviceInfoProto(device)).setCredentialsBody(credentials.getCredentialsValue()).build()).build(); + .setValidateTokenResponseMsg(builder.build()).build(); } catch (JsonProcessingException e) { log.warn("[{}] Failed to lookup device by id", deviceId, e); return getEmptyTransportApiResponse(); diff --git a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/AbstractTransportService.java b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/AbstractTransportService.java index 5a81b97aed..b5e5d74b1d 100644 --- a/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/AbstractTransportService.java +++ b/common/transport/transport-api/src/main/java/org/thingsboard/server/common/transport/service/AbstractTransportService.java @@ -40,7 +40,7 @@ public abstract class AbstractTransportService implements TransportService { private boolean rateLimitEnabled; @Value("${transport.rate_limits.tenant}") private String perTenantLimitsConf; - @Value("${transport.rate_limits.tenant}") + @Value("${transport.rate_limits.device}") private String perDevicesLimitsConf; @Value("${transport.sessions.inactivity_timeout}") private long sessionInactivityTimeout; From 0e4f72b480d768c209bf33d2f36c59ae23020a44 Mon Sep 17 00:00:00 2001 From: Andrew Shvayka Date: Mon, 31 Dec 2018 10:58:04 +0200 Subject: [PATCH 19/27] Issue #1346: Added note to the node details about max fetch size --- .../org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java | 1 + 1 file changed, 1 insertion(+) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index b04b5b36c1..a9e97497e5 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -59,6 +59,7 @@ import static org.thingsboard.server.common.data.kv.Aggregation.NONE; nodeDescription = "Add Message Originator Telemetry for selected time range into Message Metadata\n", nodeDetails = "The node allows you to select fetch mode FIRST/LAST/ALL to fetch telemetry of certain time range that are added into Message metadata without any prefix. " + "If selected fetch mode ALL Telemetry will be added like array into Message Metadata where key is Timestamp and value is value of Telemetry. " + + "Note: The maximum size of the fetched array is 1000 records. " + "If selected fetch mode FIRST or LAST Telemetry will be added like string without Timestamp", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbEnrichmentNodeGetTelemetryFromDatabase") From 354f8910bf4d79711f2a441ad6eb5470f432e2e8 Mon Sep 17 00:00:00 2001 From: yefimov-andrey Date: Wed, 2 Jan 2019 14:14:31 +0200 Subject: [PATCH 20/27] Fixed URL templating (#1359) * fixed conflicts * fixed URL templating * added springfox version * moved dependency declaration * further fix * more fixes * optimized import * reverting to first version to check * reverted to version before new dependency * added dependency with version in correct place * added to dependencyManagement --- application/pom.xml | 4 ++++ .../actors/ruleChain/RuleNodeActorMessageProcessor.java | 1 - .../org/thingsboard/server/config/SwaggerConfiguration.java | 3 ++- pom.xml | 6 ++++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/application/pom.xml b/application/pom.xml index 6280d0031f..d7b560189e 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -264,6 +264,10 @@ org.javadelight delight-nashorn-sandbox + + io.springfox.ui + springfox-swagger-ui-rfc6570 + diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java index 7f200e176e..452b9d7eb8 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeActorMessageProcessor.java @@ -17,7 +17,6 @@ package org.thingsboard.server.actors.ruleChain; import akka.actor.ActorContext; import akka.actor.ActorRef; -import akka.event.LoggingAdapter; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; diff --git a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java index 2254cf3da0..52eef828f8 100644 --- a/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java +++ b/application/src/main/java/org/thingsboard/server/config/SwaggerConfiguration.java @@ -64,7 +64,8 @@ public class SwaggerConfiguration { .paths(apiPaths()) .build() .securitySchemes(newArrayList(jwtTokenKey())) - .securityContexts(newArrayList(securityContext())); + .securityContexts(newArrayList(securityContext())) + .enableUrlTemplating(true); } private ApiKey jwtTokenKey() { diff --git a/pom.xml b/pom.xml index b3182f74ff..bfb5caa1ce 100755 --- a/pom.xml +++ b/pom.xml @@ -70,6 +70,7 @@ 2.19.1 3.0.2 2.6.1 + 1.0.0 1.56 2.0.1 2.4.0 @@ -794,6 +795,11 @@ bucket4j-core ${bucket4j.version} + + io.springfox.ui + springfox-swagger-ui-rfc6570 + ${springfox-swagger-ui-rfc6570.version} + From 4a1916668a83186e185af8e25794f2ffd65fb38e Mon Sep 17 00:00:00 2001 From: ShvaykaD Date: Fri, 4 Jan 2019 12:58:46 +0200 Subject: [PATCH 21/27] fix TbGetTelemetryNode (#1377) * fix TbGetTelemetryNode * refactoring ui TbGetTelemetryNode * update license header * refactoring TbGetTelemetryNode * fix imports and update license header * refactoring TbGetTelemetryNode * replace typo * fix TbGetTelemetryNode * fix TbGetTelemetryNode * fix TbGetTelemetryNode --- .../thingsboard/rule/engine/metadata/TbGetTelemetryNode.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java index a9e97497e5..d636339022 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/metadata/TbGetTelemetryNode.java @@ -88,7 +88,9 @@ public class TbGetTelemetryNode implements TbNode { ctx.tellFailure(msg, new IllegalStateException("Telemetry is not selected!")); } else { try { - checkMetadataKeyPatterns(msg); + if (config.isUseMetadataIntervalPatterns()) { + checkMetadataKeyPatterns(msg); + } ListenableFuture> list = ctx.getTimeseriesService().findAll(ctx.getTenantId(), msg.getOriginator(), buildQueries(msg)); DonAsynchron.withCallback(list, data -> { process(data, msg); From 0a950a49160860a3f5111857b911674c69d3f8d4 Mon Sep 17 00:00:00 2001 From: Maksym Dudnik Date: Thu, 3 Jan 2019 10:12:29 +0200 Subject: [PATCH 22/27] added_initBounds_param_to_prevent_fit_to_bounds_on_every_update --- ui/src/app/widget/lib/map-widget2.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ui/src/app/widget/lib/map-widget2.js b/ui/src/app/widget/lib/map-widget2.js index 0ed70c50cc..461f16f9e6 100644 --- a/ui/src/app/widget/lib/map-widget2.js +++ b/ui/src/app/widget/lib/map-widget2.js @@ -60,6 +60,8 @@ export default class TbMapWidgetV2 { var minZoomLevel = this.drawRoutes ? 18 : 15; + this.initBounds = true; + var initCallback = function() { tbMap.update(); tbMap.resize(); @@ -454,9 +456,10 @@ export default class TbMapWidgetV2 { tbMap.map.extendBoundsWithMarker(bounds, location.marker); } } - if (locationsChanged) { - tbMap.map.fitBounds(bounds); - } + if (locationsChanged && tbMap.initBounds) { + tbMap.map.fitBounds(bounds); + tbMap.initBounds = false; + } } function createTooltipContent(tooltip, data, datasources) { From 49d623391ef9fb1b5a681dec35de9f3b9941b032 Mon Sep 17 00:00:00 2001 From: Maksym Dudnik Date: Fri, 4 Jan 2019 11:52:56 +0200 Subject: [PATCH 23/27] map-widget2_and_subscription_file_update --- ui/src/app/api/subscription.js | 6 ++++++ ui/src/app/widget/lib/map-widget2.js | 15 +++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ui/src/app/api/subscription.js b/ui/src/app/api/subscription.js index 4a38f7166c..4ac98b5c8c 100644 --- a/ui/src/app/api/subscription.js +++ b/ui/src/app/api/subscription.js @@ -648,6 +648,12 @@ export default class Subscription { } dataUpdated(sourceData, datasourceIndex, dataKeyIndex, apply) { + for (var x = 0; x < this.datasourceListeners.length; x++) { + this.datasources[x].dataReceived = this.datasources[x].dataReceived === true; + if (this.datasourceListeners[x].datasourceIndex === datasourceIndex && sourceData.data.length > 0) { + this.datasources[x].dataReceived = true; + } + } this.notifyDataLoaded(); var update = true; var currentData; diff --git a/ui/src/app/widget/lib/map-widget2.js b/ui/src/app/widget/lib/map-widget2.js index 461f16f9e6..d969c48f64 100644 --- a/ui/src/app/widget/lib/map-widget2.js +++ b/ui/src/app/widget/lib/map-widget2.js @@ -60,7 +60,8 @@ export default class TbMapWidgetV2 { var minZoomLevel = this.drawRoutes ? 18 : 15; - this.initBounds = true; + + var initCallback = function() { tbMap.update(); @@ -89,6 +90,9 @@ export default class TbMapWidgetV2 { } else if (mapProvider === 'tencent-map') { this.map = new TbTencentMap($element,this.utils, initCallback, this.defaultZoomLevel, this.dontFitMapBounds, minZoomLevel, settings.tmApiKey, settings.tmDefaultMapType); } + + + tbMap.initBounds = true; } setCallbacks(callbacks) { @@ -444,6 +448,7 @@ export default class TbMapWidgetV2 { } function updateLocations(data, datasources) { + var locationsChanged = false; var bounds = tbMap.map.createBounds(); var dataMap = toLabelValueMap(data, datasources); @@ -457,8 +462,11 @@ export default class TbMapWidgetV2 { } } if (locationsChanged && tbMap.initBounds) { - tbMap.map.fitBounds(bounds); - tbMap.initBounds = false; + tbMap.initBounds = !datasources.every( + function (ds) { + return ds.dataReceived === true; + }); + tbMap.map.fitBounds(bounds); } } @@ -480,7 +488,6 @@ export default class TbMapWidgetV2 { content = fillPattern(settings.tooltipPattern, settings.tooltipReplaceInfo, data); return fillPatternWithActions(content, 'onTooltipAction', tooltip.markerArgs); } - if (this.map && this.map.inited() && this.subscription) { if (this.subscription.data) { if (!this.locations) { From 64d3006cb9b3207b60cd417644bdb019f95548ae Mon Sep 17 00:00:00 2001 From: aestal <32489326+aestal@users.noreply.github.com> Date: Fri, 11 Jan 2019 21:56:06 +0100 Subject: [PATCH 24/27] Update Spanish translation (#1380) * Icon section * Widget-config section * Widgets-bundle section * Widget section * User section * Tenant section * Rulenode section * Rulechain section * login section * grid section * extension section * event section * entity section * device section * dashboard section * customer section * common section * audit-log section * attribute section * asset section * alarm section * admin section * action section * access section * More improvements * Added missing messages * Missing messages translation * Entity View Spanish translation --- ui/src/app/locale/locale.constant-es_ES.json | 662 ++++++++++--------- 1 file changed, 343 insertions(+), 319 deletions(-) diff --git a/ui/src/app/locale/locale.constant-es_ES.json b/ui/src/app/locale/locale.constant-es_ES.json index 7b0214190b..2a40c8660c 100644 --- a/ui/src/app/locale/locale.constant-es_ES.json +++ b/ui/src/app/locale/locale.constant-es_ES.json @@ -2,9 +2,9 @@ "access": { "unauthorized": "No autorizado", "unauthorized-access": "Acceso no autorizado", - "unauthorized-access-text": "Debe registrarse para tener acceso a este recurso!", + "unauthorized-access-text": "¡Debe registrarse para tener acceso a este recurso!", "access-forbidden": "Acceso Prohibido", - "access-forbidden-text": "No tiene derechos para acceder a esta ubicación!
Intente registrarse con otro usuario si aún desea acceder a esta ubicación.", + "access-forbidden-text": "No tiene permisos para acceder a esta ubicación!
Intente registrarse con otro usuario si aún desea acceder a esta ubicación.", "refresh-token-expired": "La sesión ha expirado", "refresh-token-failed": "No se puede actualizar la sesión" }, @@ -14,7 +14,7 @@ "save": "Guardar", "saveAs": "Guardar como", "cancel": "Cancelar", - "ok": "OK", + "ok": "Aceptar", "delete": "Eliminar", "add": "Agregar", "yes": "Si", @@ -30,17 +30,17 @@ "apply": "Aplicar", "apply-changes": "Aplicar cambios", "edit-mode": "Modo edición", - "enter-edit-mode": "Ingresar modo edición", + "enter-edit-mode": "Entrar en modo edición", "decline-changes": "Descartar cambios", "close": "Cerrar", "back": "Atras", "run": "Ejecutar", - "sign-in": "Registrarse!", + "sign-in": "¡Registrarse!", "edit": "Editar", "view": "Ver", "create": "Crear", "drag": "Arrastrar", - "refresh": "Refrecar", + "refresh": "Actualizar", "undo": "Deshacer", "copy": "Copiar", "paste": "Pegar", @@ -48,7 +48,7 @@ "paste-reference": "Pegar referencia", "import": "Importar", "export": "Exportar", - "share-via": "Share via {{provider}}" + "share-via": "Compartir via {{provider}}" }, "aggregation": { "aggregation": "Agregación", @@ -68,11 +68,11 @@ "outgoing-mail": "Servidor de correo", "outgoing-mail-settings": "Configuración del servidor de correo de salida", "system-settings": "Configuración del sistema", - "test-mail-sent": "Correo de prueba fue enviado exitosamente!", + "test-mail-sent": "¡El correo de prueba fue enviado correctamente!", "base-url": "URL base", "base-url-required": "URL base es requerida.", "mail-from": "Correo desde", - "mail-from-required": "Correo Desde es requerido.", + "mail-from-required": "Correo desde es requerido.", "smtp-protocol": "Protocolo SMTP", "smtp-host": "Host SMTP", "smtp-host-required": "Host SMTP es requerido.", @@ -93,11 +93,11 @@ "alarm-required": "Alarma es requerida", "alarm-status": "Estado de la alarma", "search-status": { - "ANY": "Alguna", - "ACTIVE": "Activa", - "CLEARED": "Borrada", - "ACK": "Reconocida", - "UNACK": "Ignorada" + "ANY": "Todas", + "ACTIVE": "Activas", + "CLEARED": "Borradas", + "ACK": "Reconocidas", + "UNACK": "Ignoradas" }, "display-status": { "ACTIVE_UNACK": "Activa ignorada", @@ -105,10 +105,10 @@ "CLEARED_UNACK": "Borrada ignorada", "CLEARED_ACK": "Borrada reconocida" }, - "no-alarms-prompt": "Alarmas no encontradas", + "no-alarms-prompt": "No se encontraron alarmas", "created-time": "Tiempo de creación", "type": "Tipo", - "severity": "Severidad", + "severity": "Criticidad", "originator": "Origen", "originator-type": "Tipo de origen", "details": "Detalles", @@ -119,27 +119,27 @@ "ack-time": "Tiempo de reconocimiento", "clear-time": "Tiempo de borrado", "severity-critical": "Crítica", - "severity-major": "Mayor", - "severity-minor": "Menor", + "severity-major": "Alta", + "severity-minor": "Baja", "severity-warning": "Alerta", "severity-indeterminate": "Indeterminada", "acknowledge": "Reconocer", "clear": "Borrar", "search": "buscar alarmas", - "selected-alarms": "{ count, plural, 1 {1 alarm} other {# alarms} } seleccionadas", + "selected-alarms": "{ count, plural, 1 {1 alarma} other {# alarmas} } seleccionadas", "no-data": "No hay datos para mostrar", "polling-interval": "Intervalo de sondeo de alarmas (seg)", "polling-interval-required": "Intervalo de sondeo de alarmas es requerido.", "min-polling-interval-message": "Se permite al menos 1 segundo de intervalo de sondeo.", - "aknowledge-alarms-title": "Reconocer { count, plural, 1 {1 alarm} other {# alarms} }", - "aknowledge-alarms-text": "¿Está seguro de que desea reconocer { count, plural, 1 {1 alarm} other {# alarms} }?", - "aknowledge-alarm-title": "Acknowledge Alarm", - "aknowledge-alarm-text": "Are you sure you want to acknowledge Alarm?", - "clear-alarms-title": "Borrar { count, plural, 1 {1 alarm} other {# alarms} }", - "clear-alarms-text": "¿Está seguro de que desea borrar { count, plural, 1 {1 alarm} other {# alarms} }?", - "clear-alarm-title": "Clear Alarm", - "clear-alarm-text": "Are you sure you want to clear Alarm?", - "alarm-status-filter": "Alarm Status Filter" + "aknowledge-alarms-title": "Reconocer { count, plural, 1 {1 alarma} other {# alarmas} }", + "aknowledge-alarms-text": "¿Está seguro de que desea reconocer { count, plural, 1 {1 alarma} other {# alarmas} }?", + "aknowledge-alarm-title": "Reconocer alarma", + "aknowledge-alarm-text": "¿Está seguro que quirere reconocer la alarma?", + "clear-alarms-title": "Quitar { count, plural, 1 {1 alarma} other {# alarmas} }", + "clear-alarms-text": "¿Está seguro de que desea quitar { count, plural, 1 {1 alarma} other {# alarmas}?", + "clear-alarm-title": "Quitar alarma", + "clear-alarm-text": "¿Está seguro que quiere quitar la alarma?", + "alarm-status-filter": "Filtro de estado de alarma" }, "alias": { "add": "Agregar alias", @@ -151,24 +151,29 @@ "filter-type-entity-list": "Lista de entidades", "filter-type-entity-name": "Nombre de entidad", "filter-type-state-entity": "Entidad del panel de estados", - "filter-type-state-entity-description": "Entidad tomada desde los parámetro del panel de estados", + "filter-type-state-entity-description": "Entidad tomada desde los parámetros del panel de estados", "filter-type-asset-type": "Tipo de activo", "filter-type-asset-type-description": "Activos de tipo '{{assetType}}'", - "filter-type-asset-type-and-name-description": "Activos de tipo '{{assetType}}' y con nombre comenzando con '{{prefix}}'", + "filter-type-asset-type-and-name-description": "Activos del tipo '{{assetType}}' y su nombre empieza con '{{prefix}}'", "filter-type-device-type": "Tipo de dispositivo", "filter-type-device-type-description": "Dispositivos de tipo '{{deviceType}}'", - "filter-type-device-type-and-name-description": "Dispositivos de tipo '{{deviceType}}' y con nombre comenzando con '{{prefix}}'", + "filter-type-device-type-and-name-description": "Dispositivos del tipo '{{deviceType}}' y su nombre empieza con '{{prefix}}'", + "filter-type-entity-view-type": "Tipo de vista de entidad", + "filter-type-entity-view-type-description": "Vista de entidad del tipo '{{entityView}}'", + "filter-type-entity-view-type-and-name-description": "Las vista de entidad del tipo '{{entityView}}' y cuyo nombre comienza con '{{prefix}}'", "filter-type-relations-query": "Consulta de relaciones", "filter-type-relations-query-description": "{{entities}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", "filter-type-asset-search-query": "Consultar búsqueda de activos", "filter-type-asset-search-query-description": "Activos con tipos {{assetTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", "filter-type-device-search-query": "Consultar búqueda de dispositivos", "filter-type-device-search-query-description": "Dispositivos con tipos {{deviceTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", + "filter-type-entity-view-search-query": "Consultar vista de entidad", + "filter-type-entity-view-search-query-description": "Las vista de entidad de tipo {{entityViewTypes}} que tienen {{relationType}} relación {{direction}} {{rootEntity}}", "entity-filter": "Filtro de entidad", "resolve-multiple": "Resolver como entidades múltiples", "filter-type": "Tipo de filtro", "filter-type-required": "Tipo de filtro es requerido.", - "entity-filter-no-entity-matched": "Entidades que coincidan con el filtro especificado no fueron encontradas.", + "entity-filter-no-entity-matched": "No se encontraron entidades que coincidan con el filtro especificado.", "no-entity-filter-specified": "No se especificó el filtro de entidad", "root-state-entity": "Utilizar la entidad del panel de estados como raíz", "root-entity": "Entidad raíz", @@ -185,13 +190,13 @@ "asset": "Activo", "assets": "Activos", "management": "Gestión de activos", - "view-assets": "Ver Activos", - "add": "Agregar Activo", + "view-assets": "Ver activos", + "add": "Agregar activo", "assign-to-customer": "Asignar al cliente", - "assign-asset-to-customer": "Asignar Activo(s) Al Cliente", - "assign-asset-to-customer-text": "Por favor seleccionar los activos para asignar al cliente", - "no-assets-text": "Activos no encontrados", - "assign-to-customer-text": "Por favor seleccionar el cliente para asignar el(los) activo(s)", + "assign-asset-to-customer": "Asignar activo(s) al cliente", + "assign-asset-to-customer-text": "Por favor, seleccione los activos para asignar al cliente", + "no-assets-text": "No se encontraron activos", + "assign-to-customer-text": "Por favor, seleccione el cliente para asignar el(los) activo(s)", "public": "Público", "assignedToCustomer": "Asignado al cliente", "make-public": "Hacer público el activo", @@ -202,9 +207,9 @@ "asset-type": "Tipo de activo", "asset-type-required": "El tipo de activo es requerido.", "select-asset-type": "Seleccionar tipo de activo", - "enter-asset-type": "Ingresar tipo de activo", + "enter-asset-type": "Introduzca el tipo de activo", "any-asset": "Algún activo", - "no-asset-types-matching": "Tipos de activos que coincidan con '{{entitySubtype}}' no fueron encontrados.", + "no-asset-types-matching": "No se encontraron tipos de activos que coincidan con '{{entitySubtype}}'.", "asset-type-list-empty": "No se seleccionaron tipos de activos.", "asset-types": "Tipos de activos", "name": "Nombre", @@ -217,16 +222,16 @@ "add-asset-text": "Agregar nuevos activos", "asset-details": "Detalles del activo", "assign-assets": "Asignar activos", - "assign-assets-text": "Asignar { count, plural, 1 {1 asset} other {# assets} } al cliente", + "assign-assets-text": "Asignar { count, plural, 1 {1 activo} other {# activos} } al cliente", "delete-assets": "Eliminar activos", "unassign-assets": "Anular asignación de activos", - "unassign-assets-action-title": "Anular asignación { count, plural, 1 {1 asset} other {# assets} } del cliente", + "unassign-assets-action-title": "Anular asignación { count, plural, 1 {1 activo} other {# activos} } del cliente", "assign-new-asset": "Asignar nuevo activo", "delete-asset-title": "¿Está seguro de que desea eliminar el activo '{{assetName}}'?", - "delete-asset-text": "Tener cuidado, después de la confirmación, el activo y todos los datos relacionados se volverán irrecuperables.", - "delete-assets-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 asset} other {# assets} }?", - "delete-assets-action-title": "Eliminar { count, plural, 1 {1 asset} other {# assets} }", - "delete-assets-text": "Tener cuidado, después de la confirmación se eliminarán todos los activos seleccionados y todos los datos relacionados se volverán irrecuperables.", + "delete-asset-text": "¡Cuidado! Después de la confirmación, el activo y todos los datos relacionados serán irrecuperables.", + "delete-assets-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 activos} other {# activos} }?", + "delete-assets-action-title": "Eliminar { count, plural, 1 {1 activo} other {# activos} }", + "delete-assets-text": "¡Cuidado! Después de la confirmación se eliminarán todos los activos seleccionados y todos los datos relacionados serán irrecuperables.", "make-public-asset-title": "¿Está seguro de que desea que el activo '{{assetName}}' sea público?", "make-public-asset-text": "Después de la confirmación, el activo y todos sus datos se harán públicos y accesibles por otros.", "make-private-asset-title": "¿Está seguro de que desea que el activo '{{assetName}}' sea privado?", @@ -234,12 +239,12 @@ "unassign-asset-title": "¿Está seguro de que desea anular asignación del activo '{{assetName}}'?", "unassign-asset-text": "Después de la confirmación, se anulará asignación del activo y no será accesible por el cliente.", "unassign-asset": "Anular asignación activo", - "unassign-assets-title": "¿Está seguro de que desea anular asignación { count, plural, 1 {1 asset} other {# assets} }?", + "unassign-assets-title": "¿Está seguro de que desea anular asignación { count, plural, 1 {1 activo} other {# activos} }?", "unassign-assets-text": "Después de la confirmación, se anulará asignación de todos los activos seleccionados y no serán accesibles por el cliente", "copyId": "Copiar ID del activo", "idCopiedMessage": "ID del activo has sido copiada al portapapeles", "select-asset": "Seleccionar activo", - "no-assets-matching": "Activos que coincidan con '{{entity}}' no fueron encontrados.", + "no-assets-matching": "No se encontraron activos que coincidan con '{{entity}}'.", "asset-required": "El activo es requerido", "name-starts-with": "El nombre del activo comienza con" }, @@ -257,25 +262,25 @@ "key-required": "La clave del aributo es requerida.", "value": "Valor", "value-required": "Valor del atributo es requerido.", - "delete-attributes-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 attribute} other {# attributes} }?", - "delete-attributes-text": "Tener cuidado, después de la confirmación, se eliminarán todos los atributos seleccionados.", + "delete-attributes-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 atributo} other {# atributos} }?", + "delete-attributes-text": "¡Cuidado! Después de la confirmación, se eliminarán todos los atributos seleccionados.", "delete-attributes": "Eliminar atributos", - "enter-attribute-value": "Ingresar valor del atributo", + "enter-attribute-value": "Introduzca el valor del atributo", "show-on-widget": "Mostrar en widget", "widget-mode": "Modo widget", "next-widget": "Widget siguiente", "prev-widget": "Widget previo", "add-to-dashboard": "Agregar al panel", "add-widget-to-dashboard": "Agregar widget al panel", - "selected-attributes": "{ count, plural, 1 {1 attribute} other {# attributes} } seleccionados", + "selected-attributes": "{ count, plural, 1 {1 atributo} other {# atributos} } seleccionados", "selected-telemetry": "{ count, plural, 1 {1 telemetry unit} other {# telemetry units} } seleccionadas" }, "audit-log": { - "audit": "Auditar", - "audit-logs": "Auditar Registros", + "audit": "Auditoría", + "audit-logs": "Registros de auditoría", "timestamp": "Marca de tiempo", - "entity-type": "Tipo de Entidad", - "entity-name": "Nombre de Entidad", + "entity-type": "Tipo de entidad", + "entity-name": "Nombre de entidad", "user": "Usuario", "type": "Tipo", "status": "Estado", @@ -287,7 +292,7 @@ "type-attributes-deleted": "Atributos eliminados", "type-rpc-call": "Llamada RPC", "type-credentials-updated": "Credenciales actualizadas", - "type-assigned-to-customer": "Asignado al Cliente", + "type-assigned-to-customer": "Asignado al cliente", "type-unassigned-from-customer": "Asignación anulada del cliente", "type-activated": "Activado", "type-suspended": "Suspendido", @@ -298,18 +303,18 @@ "type-relations-delete": "Toda relación eliminada", "type-alarm-ack": "Reconocida", "type-alarm-clear": "Borrada", - "status-success": "Éxito", - "status-failure": "Falla", - "audit-log-details": "Auditar detalles de regisstro", - "no-audit-logs-prompt": "Registros no encontrados", + "status-success": "Correcto", + "status-failure": "Erróneo", + "audit-log-details": "Detalle del registro de auditoría", + "no-audit-logs-prompt": "No se encontraron registros", "action-data": "Datos de acción", - "failure-details": "Detalles de falla", + "failure-details": "Detalles del error", "search": "Buscar registros de auditoría", "clear-search": "Borrar búsqueda" }, "confirm-on-exit": { "message": "Tiene cambios sin guardar. ¿Está seguro de que desea salir de esta página?", - "html-message": "Tiene cambios sin guardar..
¿Está seguro de que desea salir de esta página?", + "html-message": "Tiene cambios sin guardar.
¿Está seguro de que desea salir de esta página?", "title": "Cambios sin guardar" }, "contact": { @@ -327,9 +332,9 @@ "common": { "username": "Nombre de usuario", "password": "Contraseña", - "enter-username": "Ingresar nombre de usuario", - "enter-password": "Ingresar contraseña", - "enter-search": "Ingresar búsqueda" + "enter-username": "Introduzca nombre de usuario", + "enter-password": "Introduzca contraseña", + "enter-search": "Introduzca búsqueda" }, "content-type": { "json": "Json", @@ -340,15 +345,15 @@ "customer": "Cliente", "customers": "Clientes", "management": "Gestión del cliente", - "dashboard": "Panel del Cliente", - "dashboards": "Paneles del Cliente", - "devices": "Dispositivos del Cliente", - "entity-views": "Customer Entity Views", + "dashboard": "Panel del cliente", + "dashboards": "Paneles del cliente", + "devices": "Dispositivos del cliente", + "entity-views": "Vistas de entidad del cliente", "assets": "Activos del Cliente", - "public-dashboards": "Paneles Públicos", - "public-devices": "Dispositivos Públicos", - "public-assets": "Activos Públicos", - "public-entity-views": "Public Entity Views", + "public-dashboards": "Paneles públicos", + "public-devices": "Dispositivos públicos", + "public-assets": "Activos públicos", + "public-entity-views": "Vista de entidad públicas", "add": "Agregar cliente", "delete": "Eliminar cliente", "manage-customer-users": "Gestionar usuarios del cliente", @@ -359,13 +364,13 @@ "manage-customer-assets": "Gestionar activos del cliente", "manage-public-assets": "Gestionar activos públicos", "add-customer-text": "Agregar nuevo cliente", - "no-customers-text": "Clientes no encontrados", + "no-customers-text": "No se encontraron clientes", "customer-details": "Detalles del cliente", "delete-customer-title": "¿Está seguro de que desea eliminar al cliente '{{customerTitle}}'?", - "delete-customer-text": "Tener cuidado, después de la confirmación, el cliente y todos los datos relacionados se volverán irrecuperables.", - "delete-customers-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 customer} other {# customers} }?", - "delete-customers-action-title": "Eliminar { count, plural, 1 {1 customer} other {# customers} }", - "delete-customers-text": "Tener cuidado, después de la confirmación, todos los clientes seleccionados serán eliminados y todos los datos relacionados se volverán irrecuperables.", + "delete-customer-text": "¡Cuidado! Después de la confirmación, el cliente y todos los datos relacionados serán irrecuperables.", + "delete-customers-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 cliente} other {# clientes} }?", + "delete-customers-action-title": "Eliminar { count, plural, 1 {1 cliente} other {# clientes} }", + "delete-customers-text": "¡Cuidado! Después de la confirmación, todos los clientes seleccionados serán eliminados y todos los datos relacionados serán irrecuperables.", "manage-users": "Gestionar usuarios", "manage-assets": "Gestionar activos", "manage-devices": "Gestionar dispositivos", @@ -378,7 +383,7 @@ "copyId": "Copiar ID del cliente", "idCopiedMessage": "ID del cliente ha sido copiada al portapapeles", "select-customer": "Seleccionar cliente", - "no-customers-matching": "Clientes que coincidan con '{{entity}}' no fueron encontrados.", + "no-customers-matching": "No se encontraron clientes que coincidan con '{{entity}}'.", "customer-required": "El cliente es requerido", "select-default-customer": "Seleccionar cliente predeterminado", "default-customer": "Cliente predeterminado", @@ -394,22 +399,22 @@ "dashboard": "Panel", "dashboards": "Paneles", "management": "Gestión del panel", - "view-dashboards": "Ver Panel", - "add": "Agregar Paneles", - "assign-dashboard-to-customer": "Asignar Panel(es) Al Cliente", - "assign-dashboard-to-customer-text": "Por favor seleccionar los paneles para asignar al cliente", - "assign-to-customer-text": "Por favor seleccionar el cliente para asignar el(los) panel(es)", + "view-dashboards": "Ver panel", + "add": "Agregar paneles", + "assign-dashboard-to-customer": "Asignar panel(es) al cliente", + "assign-dashboard-to-customer-text": "Por favor selecciona los paneles para asignar al cliente", + "assign-to-customer-text": "Por favor selecciona el cliente para asignar el(los) panel(es)", "assign-to-customer": "Asignar al cliente", "unassign-from-customer": "Anular asignación del cliente", "make-public": "Hacer panel público", - "make-private": "Hcer panel privado", + "make-private": "Hacer panel privado", "manage-assigned-customers": "Gestionar clientes asignados", "assigned-customers": "Clientes asignados", - "assign-to-customers": "Asignar Panel(es) Al(Los) Cliente(s)", + "assign-to-customers": "Asignar panel(es) al(los) cliente(s)", "assign-to-customers-text": "Por favor seleccionar los clientes para asignar el(los) panel(es)", - "unassign-from-customers": "Anular Asignación Del(De Los) Panel(es) De Los Clientes", - "unassign-from-customers-text": "Por favor seeccionar los clientes oara anular asignación del(de los) panel(es)", - "no-dashboards-text": "Paneles no encontrados", + "unassign-from-customers": "Anular asignación del(de los) panel(es) de los clientes", + "unassign-from-customers-text": "Por favor selecciona los clientes para anular asignación del(de los) panel(es)", + "no-dashboards-text": "No se encontraron paneles", "no-widgets": "Sin widgets configurados", "add-widget": "Agregar nuevo widget", "title": "Título", @@ -419,7 +424,7 @@ "title-required": "El título es requerido.", "description": "Descripción", "details": "Detalles", - "dashboard-details": "Detalles del Panel", + "dashboard-details": "Detalles del panel", "add-dashboard-text": "Agregar nuevo panel", "assign-dashboards": "Asignar paneles", "assign-new-dashboard": "Aignar nuevo panel", @@ -429,10 +434,10 @@ "unassign-dashboards": "Anular asignación de paneles", "unassign-dashboards-action-title": "Anular asignación { count, plural, 1 {1 dashboard} other {# dashboards} } del cliente", "delete-dashboard-title": "¿Está seguro de que desea eliminar el panel '{{dashboardTitle}}'?", - "delete-dashboard-text": "Tener cuidado, después de la confirmación, el panel y todos los datos relacionados se volverán irrecuperables.", + "delete-dashboard-text": "¡Cuidado! Después de la confirmación, el panel y todos los datos relacionados serán irrecuperables.", "delete-dashboards-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 dashboard} other {# dashboards} }?", "delete-dashboards-action-title": "Eliminar { count, plural, 1 {1 dashboard} other {# dashboards} }", - "delete-dashboards-text": "Tener cuidado, después de la confirmación, todos los paneles seleccionados serán eliminados y todos los datos relacionados se volverán irrecuperables.", + "delete-dashboards-text": "¡Cuidado! Después de la confirmación, todos los paneles seleccionados serán eliminados y todos los datos relacionados serán irrecuperables.", "unassign-dashboard-title": "¿Está seguro de que desea anular la asignación del panel '{{dashboardTitle}}'?", "unassign-dashboard-text": "Después de la confirmación, se anulará la asignación del panel y no será accesible por el cliente.", "unassign-dashboard": "Anular asignación del panel", @@ -460,25 +465,25 @@ "no-image": "Ninguna imagen seleccionada", "drop-image": "Colocar una imagen o hacer clic para seleccionar un archivo para cargar.", "settings": "Configuración", - "columns-count": "Conteo de columnas", - "columns-count-required": "Conteo de columnas es requerido.", - "min-columns-count-message": "Solamente contar 10 columnas como mínimo es permitido", - "max-columns-count-message": "Solamente contar 1000 columnas como máximo es permitiddo", + "columns-count": "Número de columnas", + "columns-count-required": "Número de columnas es requerido.", + "min-columns-count-message": "Sólo está permitido 10 columnas como mínimo.", + "max-columns-count-message": "Sólo está permitido 1000 columnas como máximo.", "widgets-margins": "Margen entre widgets", "horizontal-margin": "Margen horizontal", "horizontal-margin-required": "El valor del margen horizontal es requerido.", - "min-horizontal-margin-message": "Solamente es permitido el 0 como valor mínimo para el margen horizontal", - "max-horizontal-margin-message": "Solamente es permitido el 50 como valor máximo para el margen horizontal", + "min-horizontal-margin-message": "Sólo está permitido el 0 como valor mínimo para el margen horizontal", + "max-horizontal-margin-message": "Sólo está permitido el 50 como valor máximo para el margen horizontal", "vertical-margin": "Margen vertical", "vertical-margin-required": "El valor del margen vertical es requerido.", - "min-vertical-margin-message": "Solamente es permitido el 0 como valor mínimo para el margen vertical.", - "max-vertical-margin-message": "Solamente es permitido el 50 como valor máximo para el margen vertical", + "min-vertical-margin-message": "Sólo está permitido el 0 como valor mínimo para el margen vertical.", + "max-vertical-margin-message": "Sólo está permitido el 50 como valor máximo para el margen vertical", "autofill-height": "Llenado automático de altura de diseño", "mobile-layout": "Configuración de diseño para móvil", "mobile-row-height": "Altura de fila para móvil, píxel", "mobile-row-height-required": "Altura de fila para móvil es requerida.", - "min-mobile-row-height-message": "Solamente es permitido 5 píxeles como valor mínimo de altura de fila para móvil.", - "max-mobile-row-height-message": "Solamente es permitido 200 píxeles como valor máximo de altura de fila para móvil.", + "min-mobile-row-height-message": "Sólo está permitido 5 píxeles como valor mínimo en la altura de fila para móvil.", + "max-mobile-row-height-message": "Sólo está permitido 200 píxeles como valor máximo en la altura de fila para móvil.", "display-title": "Mostrar título del panel", "toolbar-always-open": "Mantener la barra de herramientas abierta", "title-color": "Color del título", @@ -550,7 +555,12 @@ "alarm-fields-required": "Campos de alarma son requeridos.", "function-types": "Tipos de funciones", "function-types-required": "Tipos de funciones son requeridos.", - "maximum-function-types": "Máximo { count, plural, 1 {1 function type is allowed.} other {# function types are allowed} }" + "maximum-function-types": "Máximo { count, plural, 1 {1 function type is allowed.} other {# function types are allowed} }", + "time-description": "timestamp of the current value;", + "value-description": "the current value;", + "prev-value-description": "result of the previous function call;", + "time-prev-description": "timestamp of the previous value;", + "prev-orig-value-description": "original previous value;" }, "datasource": { "type": "Tipo de fuente de datos", @@ -558,23 +568,23 @@ "add-datasource-prompt": "Por favor agregue fuente de datos" }, "details": { - "details": "Detalles", - "edit-mode": "Modo de edición" + "edit-mode": "Modo de edición", + "toggle-edit-mode": "Cambiar mode de edición" }, "device": { "device": "Dispositivo", "device-required": "Dispositivo es requerido.", "devices": "Dispositivos", "management": "Gestión del dispositivo", - "view-devices": "Ver Dispositivos", + "view-devices": "Ver dispositivos", "device-alias": "Alias del dispositivo", "aliases": "Alias de los dispositivos", "no-alias-matching": "'{{alias}}' no encontrado.", - "no-aliases-found": "Alias no encontrados.", + "no-aliases-found": "No se encontraron alias.", "no-key-matching": "'{{key}}' no encontrado.", "no-keys-found": "Claves no encontradas.", - "create-new-alias": "Crear uno nuevo!", - "create-new-key": "Crear una nueva!", + "create-new-alias": "¡Crear uno nuevo!", + "create-new-key": "¡Crear una nueva!", "duplicate-alias-error": "Alias duplicado encontrado '{{alias}}'.
Los alias del dispositivo deben ser únicos dentro del panel.", "configure-alias": "Configurar '{{alias}}' alias", "no-devices-matching": "Dispositivos que coincidan con '{{entity}}' no fueron encontrados.", @@ -591,10 +601,10 @@ "add": "Agregar Dispositivo", "assign-to-customer": "Asignar al cliente", "assign-device-to-customer": "Asignar Dispositivo(s) Al Cliente", - "assign-device-to-customer-text": "Por favor seleccionar los dispositivos para asignar al cliente", + "assign-device-to-customer-text": "Por favor selecciona los dispositivos para asignar al cliente", "make-public": "Hacer público el dispositivo", "make-private": "Hacer privado el dispositivo", - "no-devices-text": "Dispositivos no encontrados", + "no-devices-text": "No se encontraron dispositivos", "assign-to-customer-text": "Por favor seleccionar el cliente para asignar el(los) dispositivo(s)", "device-details": "Detalles del dispositivo", "add-device-text": "Agregar nuevo dispositivo", @@ -602,11 +612,11 @@ "manage-credentials": "Gestionar credenciales", "delete": "Eliminar dispositivo", "assign-devices": "Asignar dispositivos", - "assign-devices-text": "Asignar { count, plural, 1 {1 device} other {# devices} } al cliente", + "assign-devices-text": "Asignar { count, plural, 1 {1 dispositivo} other {# dispositivos} } al cliente", "delete-devices": "Eliminar dispositivos", "unassign-from-customer": "Anular asignación del cliente", "unassign-devices": "Anular asignación de dispositivos", - "unassign-devices-action-title": "Anular asignación { count, plural, 1 {1 device} other {# devices} } del cliente", + "unassign-devices-action-title": "Anular asignación { count, plural, 1 {1 dispositivo} other {# dispositivos} } del cliente", "assign-new-device": "Asignar nuevo dispositivo", "make-public-device-title": "¿Está seguro de que desea hacer el dispositivo '{{deviceName}}' público?", "make-public-device-text": "Después de la confirmación, el dispositivo y todos sus datos se harán públicos y accesibles por otros.", @@ -614,14 +624,14 @@ "make-private-device-text": "Después de la confirmación, el dispositivo y todos sus datos se harán privados y no serán accesibles para otros.", "view-credentials": "Ver credenciales", "delete-device-title": "¿Está seguro de que desea hacer el dispositivo '{{deviceName}}'?", - "delete-device-text": "Tener cuidado, después de la confirmación, el dispositivo y todos sus datos relacionados se volverán irrecuperables.", - "delete-devices-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 device} other {# devices} }?", - "delete-devices-action-title": "Eliminar { count, plural, 1 {1 device} other {# devices} }", - "delete-devices-text": "Tener cuidado, después de la confirmación, todos los dispositivos seleccionados serán eliminados y todos los datos relacionados se volverán irrecuperables.", + "delete-device-text": "¡Cuidado! Después de la confirmación, el dispositivo y todos sus datos relacionados serán irrecuperables.", + "delete-devices-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 dispositivo} other {# dispositivos} }?", + "delete-devices-action-title": "Eliminar { count, plural, 1 {1 dispositivo} other {# dispositivos} }", + "delete-devices-text": "¡Cuidado! Después de la confirmación, todos los dispositivos seleccionados serán eliminados y todos los datos relacionados serán irrecuperables.", "unassign-device-title": "¿Está seguro de que desea anular la asignación del dispositivo '{{deviceName}}'?", "unassign-device-text": "Después de la confirmación, se anulará asignación del dispositivo y no será accesible por el cliente.", "unassign-device": "Anular asignación del dispositivo", - "unassign-devices-title": "¿Está seguro de que desea anular asignación { count, plural, 1 {1 device} other {# devices} }?", + "unassign-devices-title": "¿Está seguro de que desea anular asignación { count, plural, 1 {1 dispositivo} other {# dispositivos} }?", "unassign-devices-text": "Después de la confirmación, se anulará asignación de todos los dispositivos seleccionados y no serán accesibles por el cliente.", "device-credentials": "Credenciales del dispositivo", "credentials-type": "Tipo de credenciales", @@ -635,7 +645,7 @@ "device-type": "Tipo de dispositivo", "device-type-required": "Tipo de dispositivo es requerido.", "select-device-type": "Seleccionar tipo de dispositivo", - "enter-device-type": "Ingresar tipo de dispositivo", + "enter-device-type": "Teclee tipo de dispositivo", "any-device": "Algún dispositivo", "no-device-types-matching": "Tipos de dispositivos que coincidan con '{{entitySubtype}}' no fueron encontrados.", "device-type-list-empty": "No se seleccionaron tipos de dispositivos.", @@ -661,7 +671,7 @@ "close": "Cerrar diálogo" }, "error": { - "unable-to-connect": "No se puede conectar al servidor! Por favor revise su conexión a Internet.", + "unable-to-connect": "¡No se puede conectar al servidor! Por favor, revise su conexión a Internet.", "unhandled-error-code": "Código de error no controlado: {{errorCode}}", "unknown-error": "Error desconocido" }, @@ -671,7 +681,7 @@ "aliases": "Alias de las entidades", "entity-alias": "Alias de la entidad", "unable-delete-entity-alias-title": "No se puede borrar alias de la entidad", - "unable-delete-entity-alias-text": "Alias de la entidad '{{entityAlias}}' no piuede ser eliminado porque es usado por los siguientes widget(s):
{{widgetsList}}", + "unable-delete-entity-alias-text": "Alias de la entidad '{{entityAlias}}' no se puede eliminar porque es usado por los siguientes widget(s):
{{widgetsList}}", "duplicate-alias-error": "Alias duplicado fue encontrado '{{alias}}'.
Alias de las entidades deben ser únicos dentro del panel.", "missing-entity-filter-error": "Falta filtro para el alias '{{alias}}'.", "configure-alias": "Configurar '{{alias}}' alias", @@ -684,58 +694,58 @@ "entity-types": "Tipos de entidades", "entity-type-list": "Lista de tipos de entidades", "any-entity": "Alguna entidad", - "enter-entity-type": "Ingresara tipo de entidad", - "no-entities-matching": "Entidades que coincidan con '{{entity}}' no fueron encontradas.", - "no-entity-types-matching": "Tipos de entidades que coincidan con '{{entityType}}' no fueron encontrados.", + "enter-entity-type": "Teclee tipo de entidad", + "no-entities-matching": "No se encontraron entidades que coincidan con '{{entity}}'.", + "no-entity-types-matching": "No se encontraron tipos de entidades que coincidan con '{{entityType}}'.", "name-starts-with": "El nombre comienza con", "use-entity-name-filter": "Utilizar filtro", "entity-list-empty": "Entidades no seleccionadas.", "entity-type-list-empty": "Tipos de entidades no seleccionados.", "entity-name-filter-required": "Filtro del nombre de la entidad es requerido.", - "entity-name-filter-no-entity-matched": "Entidades que comienzan con '{{entity}}' no fueron encontradas.", + "entity-name-filter-no-entity-matched": "No se encontraron entidades que comienzan con '{{entity}}'.", "all-subtypes": "Todas", "select-entities": "Seleccionar entidades", - "no-aliases-found": "Alias no encontrados.", + "no-aliases-found": "No se encontraron alias.", "no-alias-matching": "'{{alias}}' no encontrado.", - "create-new-alias": "Crear uno nuevo!", + "create-new-alias": "¡Crear uno nuevo!", "key": "Clave", "key-name": "Nombre de clave", - "no-keys-found": "Claves no encontradas.", + "no-keys-found": "No se encontraron claves.", "no-key-matching": "'{{key}}' no encontrada.", - "create-new-key": "Crear una nueva!", + "create-new-key": "¡Crear una nueva!", "type": "Tipo", "type-required": "Tipo de entidad es requerido.", "type-device": "Dispositivo", "type-devices": "Dispositivos", - "list-of-devices": "{ count, plural, 1 {One device} other {List of # devices} }", + "list-of-devices": "{ count, plural, 1 {Un dispositivo} other {Lista de # dispositivos} }", "device-name-starts-with": "Dispositivos cuyos nombres comienzan con '{{prefix}}'", "type-asset": "Activo", "type-assets": "Activos", - "list-of-assets": "{ count, plural, 1 {One asset} other {List of # assets} }", + "list-of-assets": "{ count, plural, 1 {Un activo} other {Lista de # activos} }", "asset-name-starts-with": "Activos cuyos nombres comienzan con '{{prefix}}'", - "type-entity-view": "Entity View", - "type-entity-views": "Entity Views", - "list-of-entity-views": "{ count, plural, 1 {One entity view} other {List of # entity views} }", - "entity-view-name-starts-with": "Entity Views whose names start with '{{prefix}}'", + "type-entity-view": "Vista de entidad", + "type-entity-views": "Vistas de entidad", + "list-of-entity-views": "{ count, plural, 1 {Una vista de entidad} other {Lista de # vistas de entidad} }", + "entity-view-name-starts-with": "Vistas de entidad cuyos nombres que comienzan con '{{prefix}}'", "type-rule": "Regla", "type-rules": "Reglas", - "list-of-rules": "{ count, plural, 1 {One rule} other {List of # rules} }", + "list-of-rules": "{ count, plural, 1 {Una regla} other {Lista de # reglas} }", "rule-name-starts-with": "Reglas cuyos nombres comienzan con '{{prefix}}'", "type-plugin": "Complemento", "type-plugins": "Complementos", - "list-of-plugins": "{ count, plural, 1 {One plugin} other {List of # plugins} }", + "list-of-plugins": "{ count, plural, 1 {Un complemento} other {Lista de # complementos} }", "plugin-name-starts-with": "Complementos cuyos nombres comienzan con '{{prefix}}'", "type-tenant": "Organización", "type-tenants": "Organizaciones", - "list-of-tenants": "{ count, plural, 1 {One tenant} other {List of # tenants} }", + "list-of-tenants": "{ count, plural, 1 {Una organización} other {Lista de # organizaciones} }", "tenant-name-starts-with": "Organizaciones cuyos nombres comienzan con '{{prefix}}'", "type-customer": "Cliente", "type-customers": "Clientes", - "list-of-customers": "{ count, plural, 1 {One customer} other {List of # customers} }", + "list-of-customers": "{ count, plural, 1 {Un cliente} other {Lista de # clientes} }", "customer-name-starts-with": "Clientes cuyos nombres comienzan con '{{prefix}}'", "type-user": "Usuario", "type-users": "Usuarios", - "list-of-users": "{ count, plural, 1 {One user} other {List of # users} }", + "list-of-users": "{ count, plural, 1 {Un usuario} other {Lista de # usuarios} }", "user-name-starts-with": "Usuarios cuyos nombres comienzan con '{{prefix}}'", "type-dashboard": "Panel", "type-dashboards": "Paneles", @@ -743,103 +753,115 @@ "dashboard-name-starts-with": "Paneles cuyos nombres comienzan con '{{prefix}}'", "type-alarm": "Alarma", "type-alarms": "Alarmas", - "list-of-alarms": "{ count, plural, 1 {One alarms} other {List of # alarms} }", + "list-of-alarms": "{ count, plural, 1 {Una alarma} other {Lista de # alarmas} }", "alarm-name-starts-with": "Alarmas cuyos nombres comienzan con '{{prefix}}'", "type-rulechain": "Cadena de reglas", "type-rulechains": "Cadenas de reglas", - "list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }", - "rulechain-name-starts-with": "Cadenas reglas cuyos nombres comienzan con '{{prefix}}'", + "list-of-rulechains": "{ count, plural, 1 {Una cadena de reglas} other {Lista de # cadenas de reglas} }", + "rulechain-name-starts-with": "Cadenas de reglas cuyos nombres comienzan con '{{prefix}}'", "type-rulenode": "Nodo de reglas", "type-rulenodes": "Nodos de reglas", - "list-of-rulenodes": "{ count, plural, 1 {One rule node} other {List of # rule nodes} }", + "list-of-rulenodes": "{ count, plural, 1 {Un nodo de reglas} other {Lista de # nodos de reglas} }", "rulenode-name-starts-with": "Nodos de reglas cuyos nombres comienzan con '{{prefix}}'", "type-current-customer": "Cliente Actual", "search": "Buscar entidades", - "selected-entities": "{ count, plural, 1 {1 entity} other {# entities} } seleccionadas", + "selected-entities": "{ count, plural, 1 {1 entidad} other {# entidades} } seleccionadas", "entity-name": "Nombre de la entidad", "details": "Detalles de la entidad", "no-entities-prompt": "Entidades no encontradas", "no-data": "No hay datos para mostrar", - "columns-to-display": "Columns to Display" + "columns-to-display": "Columnas a mostrar" }, "entity-view": { - "entity-view": "Entity View", - "entity-views": "Entity Views", - "management": "Entity View management", - "view-entity-views": "View Entity Views", - "entity-view-alias": "Entity View alias", - "aliases": "Entity View aliases", - "no-alias-matching": "'{{alias}}' not found.", - "no-aliases-found": "No aliases found.", - "no-key-matching": "'{{key}}' not found.", - "no-keys-found": "No keys found.", - "create-new-alias": "Create a new one!", - "create-new-key": "Create a new one!", - "duplicate-alias-error": "Duplicate alias found '{{alias}}'.
Entity View aliases must be unique whithin the dashboard.", - "configure-alias": "Configure '{{alias}}' alias", - "no-entity-views-matching": "No entity views matching '{{entity}}' were found.", + "entity-view": "Vista de entidad", + "entity-view-required": "Vista de entidad es requerido.", + "entity-views": "Vistas de entidad", + "management": "Gestión de vistas de entidad", + "view-entity-views": "Ver vista de entidad", + "entity-view-alias": "Alias de vista de entidad", + "aliases": "Alias de vista de entidad", + "no-alias-matching": "'{{alias}}' no encontrado.", + "no-aliases-found": "No se encontraron alias.", + "no-key-matching": "'{{key}}' no encontrado.", + "no-keys-found": "No se encontraron claves.", + "create-new-alias": "¡Crear un nuevo!", + "create-new-key": "¡Crear una nueva!", + "duplicate-alias-error": "Alias duplicado'{{alias}}'.
El alias de la vista de entidad debe ser único en el dashboard.", + "configure-alias": "Configurar alias '{{alias}}'", + "no-entity-views-matching": "No se encontraron vistas que coincidan con '{{entity}}'.", "alias": "Alias", - "alias-required": "Entity View alias is required.", - "remove-alias": "Remove entity view alias", - "add-alias": "Add entity view alias", - "name-starts-with": "Entity View name starts with", - "entity-view-list": "Entity View list", - "use-entity-view-name-filter": "Use filter", - "entity-view-list-empty": "No entity views selected.", - "entity-view-name-filter-required": "Entity view name filter is required.", - "entity-view-name-filter-no-entity-view-matched": "No entity views starting with '{{entityView}}' were found.", - "add": "Add Entity View", - "assign-to-customer": "Assign to customer", - "assign-entity-view-to-customer": "Assign Entity View(s) To Customer", - "assign-entity-view-to-customer-text": "Please select the entity views to assign to the customer", - "no-entity-views-text": "No entity views found", - "assign-to-customer-text": "Please select the customer to assign the entity view(s)", - "entity-view-details": "Entity view details", - "add-entity-view-text": "Add new entity view", - "delete": "Delete entity view", - "assign-entity-views": "Assign entity views", - "assign-entity-views-text": "Assign { count, plural, 1 {1 entityView} other {# entityViews} } to customer", - "delete-entity-views": "Delete entity views", - "unassign-from-customer": "Unassign from customer", - "unassign-entity-views": "Unassign entity views", - "unassign-entity-views-action-title": "Unassign { count, plural, 1 {1 entityView} other {# entityViews} } from customer", - "assign-new-entity-view": "Assign new entity view", - "delete-entity-view-title": "Are you sure you want to delete the entity view '{{entityViewName}}'?", - "delete-entity-view-text": "Be careful, after the confirmation the entity view and all related data will become unrecoverable.", - "delete-entity-views-title": "Are you sure you want to entity view { count, plural, 1 {1 entityView} other {# entityViews} }?", - "delete-entity-views-action-title": "Delete { count, plural, 1 {1 entityView} other {# entityViews} }", - "delete-entity-views-text": "Be careful, after the confirmation all selected entity views will be removed and all related data will become unrecoverable.", - "unassign-entity-view-title": "Are you sure you want to unassign the entity view '{{entityViewName}}'?", - "unassign-entity-view-text": "After the confirmation the entity view will be unassigned and won't be accessible by the customer.", - "unassign-entity-view": "Unassign entity view", - "unassign-entity-views-title": "Are you sure you want to unassign { count, plural, 1 {1 entityView} other {# entityViews} }?", - "unassign-entity-views-text": "After the confirmation all selected entity views will be unassigned and won't be accessible by the customer.", - "entity-view-type": "Entity View type", - "entity-view-type-required": "Entity View type is required.", - "select-entity-view-type": "Select entity view type", - "enter-entity-view-type": "Enter entity view type", - "any-entity-view": "Any entity view", - "no-entity-view-types-matching": "No entity view types matching '{{entitySubtype}}' were found.", - "entity-view-type-list-empty": "No entity view types selected.", - "entity-view-types": "Entity View types", - "name": "Name", - "name-required": "Name is required.", - "description": "Description", - "events": "Events", - "details": "Details", - "copyId": "Copy entity view Id", - "assignedToCustomer": "Assigned to customer", - "unable-entity-view-device-alias-title": "Unable to delete entity view alias", - "unable-entity-view-device-alias-text": "Device alias '{{entityViewAlias}}' can't be deleted as it used by the following widget(s):
{{widgetsList}}", - "select-entity-view": "Select entity view", - "make-public": "Make entity view public", - "start-ts": "Start time", - "end-ts": "End time", - "date-limits": "Date limits", - "client-attributes": "Client attributes", - "shared-attributes": "Shared attributes", - "server-attributes": "Server attributes", - "timeseries": "Timeseries" + "alias-required": "Alias de vista de entidad es requerido.", + "remove-alias": "Borrar alias de la vista de entidad", + "add-alias": "Añadir alias a la vista de entidad", + "name-starts-with": "Nombre de vista de entidad comienza con", + "entity-view-list": "Lista de vistas de entidad", + "use-entity-view-name-filter": "Usar el filtro", + "entity-view-list-empty": "No hay vistas de entidad seleccionadas.", + "entity-view-name-filter-required": "Nombre del filtro de vista de entidad es requerido.", + "entity-view-name-filter-no-entity-view-matched": "No se econtraron vistas de entidad que comiencen con '{{entityView}}'.", + "add": "Añadir vista de entidad", + "assign-to-customer": "Asignar a cliente", + "assign-entity-view-to-customer": "Asignar vista de entidad a cliente", + "assign-entity-view-to-customer-text": "Por favor, seleccione las vistas de entidad para asignar al cliente", + "no-entity-views-text": "No se encontraron vistas de entidad", + "assign-to-customer-text": "Por favor, seleccione el cliente para asignar la vista de entidad", + "entity-view-details": "Detalles de la vista de entidad", + "add-entity-view-text": "Añadir nueva vista de entidad", + "delete": "Borrar vista de entidad", + "assign-entity-views": "Asignar vistas de entidad", + "assign-entity-views-text": "Asignar { count, plural, 1 {1 vista de entidad} other {# vistas de entidad} } a cliente", + "delete-entity-views": "Borrar vistas de entidad", + "unassign-from-customer": "Anular asignación a cliente", + "unassign-entity-views": "Anular asignación de vistas de entidad", + "unassign-entity-views-action-title": "Anular asignación { count, plural, 1 {1 vista de entidad} other {# vistas de entidad} } al cliente", + "assign-new-entity-view": "Asignar nueva vista de entidad", + "delete-entity-view-title": "¿Está seguro que quiere borrar la vista de entidad '{{entityViewName}}'?", + "delete-entity-view-text": "¡Cuidado! Después de la confirmación, la vista de la entidad y todos los datos relacionados serán irrecuperables.", + "delete-entity-views-title": "¿Está seguro que quiere borrar las vistas de entidad { count, plural, 1 {1 entityView} other {# entityViews} }?", + "delete-entity-views-action-title": "Borrar { count, plural, 1 {1 vista de entidad} other {# vistas de entidad} }", + "delete-entity-views-text": "¡Cuidado! Después de la confirmación, todas las vistas de entidades seleccionadas se eliminarán y todos los datos relacionados serán irrecuperables.", + "unassign-entity-view-title": "¿Está seguro que quiere anular la asignación de la vista de entidad '{{entityViewName}}'?", + "unassign-entity-view-text": "Después de la confirmación, la vista de la entidad quedará sin asignar y el cliente no podrá acceder a ella.", + "unassign-entity-view": "Anular asignación de la vista de entidad", + "unassign-entity-views-title": "¿Está seguro que quiere anular la asignación de { count, plural, 1 {1 vista de entidad} other {# vistas de entidad} }?", + "unassign-entity-views-text": "Después de la confirmación, todas las vistas de entidades seleccionadas quedarán sin asignar y el cliente no podrá acceder a ellas.", + "entity-view-type": "Tipo de vista de entidad", + "entity-view-type-required": "Tipo de vista de entidad es requerido.", + "select-entity-view-type": "Seleccione el tipo de vista de entidad", + "enter-entity-view-type": "Teclee el tipo de vista de entidad", + "any-entity-view": "Cualquier vista de entidad", + "no-entity-view-types-matching": "No se encontraron typos de vista de entidad '{{entitySubtype}}'.", + "entity-view-type-list-empty": "No hay tipos de vista de entidad seleccionados.", + "entity-view-types": "Tipos de vista de entidad", + "name": "Nombre", + "name-required": "Nombre es requerido.", + "description": "Descripción", + "events": "Eventos", + "details": "Detalles", + "copyId": "Copiar el Id de la vista de entidad", + "assignedToCustomer": "Asignado a cliente", + "unable-entity-view-device-alias-title": "No se puede eliminar el alias de vista de entidad", + "unable-entity-view-device-alias-text": "El alias del dispositivo '{{entityViewAlias}}' no se puede borrar porque está siendo usado por el widget(s):
{{widgetsList}}", + "select-entity-view": "Seleccionar vista de entidad", + "make-public": "Hacer pública la vista de entidad", + "start-date": "Fecha de inicio", + "start-ts": "Tiempo de inicio", + "end-date": "Fecha de finalización", + "end-ts": "Tiempo de finalización", + "date-limits": "Limites de fecha", + "client-attributes": "Atributos de cliente", + "shared-attributes": "Atributos compartidos", + "server-attributes": "Atributos de servidor", + "timeseries": "Series de tiempo", + "client-attributes-placeholder": "Atributos de cliente", + "shared-attributes-placeholder": "Atributos compartidos", + "server-attributes-placeholder": "Atributos de servidor", + "timeseries-placeholder": "Series de tiempo", + "target-entity": "Entidad objetivo", + "attributes-propagation": "Propagación de atributos", + "attributes-propagation-hint": "La vista de entidad copiará automáticamente los atributos especificados de la entidad de destino cada vez que guarde o actualice esta vista de entidad. Por razones de rendimiento, los atributos de entidad objetivo no se propagan a la vista de entidad en cada cambio de atributo. Puede habilitar la propagación automática configurando el nodo de la regla \"copiar a la vista\" en su cadena de reglas y vincular los mensajes \"Atributos de la publicación\" y \"Atributos actualizados\" al nuevo nodo de la regla.", + "timeseries-data": "Datos de series de tiempo", + "timeseries-data-hint": "Configure las claves de los datos de las series de tiempo de la entidad de destino que serán accesibles para la vista de la entidad. Los datos de esta serie temporal son de solo lectura." }, "event": { "event-type": "Tipo de evento", @@ -848,7 +870,7 @@ "type-stats": "Estadísticas", "type-debug-rule-node": "Depurar", "type-debug-rule-chain": "Depurar", - "no-events-prompt": "Eventos no encontrados", + "no-events-prompt": "No se encontraron eventos", "error": "Error", "alarm": "Alarma", "event-time": "Tiempo del evento", @@ -865,14 +887,14 @@ "data": "Datos", "event": "Evento", "status": "Estado", - "success": "Éxito", - "failed": "Falla", + "success": "Correcto", + "failed": "Erróneo", "messages-processed": "Mensajes procesados", "errors-occurred": "Errores ocurridos" }, "extension": { "extensions": "Extensiones", - "selected-extensions": "{ count, plural, 1 {1 extension} other {# extensions} } seleccionadas", + "selected-extensions": "{ count, plural, 1 {1 extension} other {# extensiones} } seleccionadas", "type": "Tipo", "key": "Clave", "value": "Valor", @@ -885,9 +907,9 @@ "add": "Agregar extensión", "edit": "Editar extensión", "delete-extension-title": "¿Está seguro de que desea eliminar la extensión '{{extensionId}}'?", - "delete-extension-text": "Tener cuidado, después de la confirmación, la extensión y todos los datos relacionados se volverán irrecuperables.", - "delete-extensions-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 extension} other {# extensions} }?", - "delete-extensions-text": "Tener cuidado, después de la confirmación, se eliminarán todas las extensiones seleccionadas.", + "delete-extension-text": "¡Cuidado! Después de la confirmación, la extensión y todos los datos relacionados serán irrecuperables.", + "delete-extensions-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 extension} other {# extensiones} }?", + "delete-extensions-text": "¡Cuidado! Después de la confirmación, se eliminarán todas las extensiones seleccionadas.", "converters": "Conversores", "converter-id": "ID del conversor", "configuration": "Configuración", @@ -986,6 +1008,8 @@ "modbus-add-server": "Agregar servidor/esclavo", "modbus-add-server-prompt": "Por favor agregar servidor/esclavo", "modbus-transport": "Transporte", + "modbus-tcp-reconnect": "Reconexión automática", + "modbus-rtu-over-tcp": "RTU sobre TCP", "modbus-port-name": "Nombre del puerto serial", "modbus-encoding": "Codificación", "modbus-parity": "Paridad", @@ -1038,12 +1062,12 @@ }, "grid": { "delete-item-title": "¿Está seguro de que desea eliminar este ítem?", - "delete-item-text": "Tener cuidado, después de la confirmación, este ítem y todos los datos relacionados se volverán irrecuperables.", - "delete-items-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 item} other {# items} }?", - "delete-items-action-title": "Eliminar { count, plural, 1 {1 item} other {# items} }", - "delete-items-text": "Tener cuidado, después de la confirmación se eliminarán todos los ítems seleccionados y todos los datos relacionados se volverán irrecuperables.", + "delete-item-text": "¡Cuiado! Después de la confirmación, este ítem y todos los datos relacionados serán irrecuperables.", + "delete-items-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 ítem} other {# ítems} }?", + "delete-items-action-title": "Eliminar { count, plural, 1 {1 ítem} other {# ítems} }", + "delete-items-text": "¡Cuidado! Después de la confirmación se eliminarán todos los ítems seleccionados y todos los datos relacionados serán irrecuperables.", "add-item-text": "Agregar nuevo ítem", - "no-items-text": "Ítems no encontrados", + "no-items-text": "No se encontraron ítems", "item-details": "Detalles del ítem", "delete-item": "Eliminar ítem", "delete-items": "Eliminar ítems", @@ -1070,7 +1094,7 @@ "js-func": { "no-return-error": "La función debe devolver el valor!", "return-type-mismatch": "La función debe devolver el valor de '{{type}}' type!", - "tidy": "Ordenado" + "tidy": "Formatear" }, "key-val": { "key": "Clave", @@ -1102,19 +1126,19 @@ }, "login": { "login": "Iniciar sesión", - "request-password-reset": "Solicitar Restablecimiento Contraseña", - "reset-password": "Restablecer Contraseña", - "create-password": "Crear Contraseña", - "passwords-mismatch-error": "Las contraseñas introducidas deben ser las mismas!", - "password-again": "Contraseña nuevamente", - "sign-in": "Por favor registrarse", + "request-password-reset": "Restablecer contraseña", + "reset-password": "Restablecer contraseña", + "create-password": "Crear contraseña", + "passwords-mismatch-error": "¡Las contraseñas introducidas deben ser iguales!", + "password-again": "Repita la contraseña de nuevo", + "sign-in": "Por favor registrese", "username": "Nombre de usuario (correo electrónico)", "remember-me": "Recordarme", - "forgot-password": "Olvidó Contraseña?", - "password-reset": "Restablecimiento de Contraseña", + "forgot-password": "¿Olvidó la contraseña?", + "password-reset": "Restablecer contraseña", "new-password": "Nueva contraseña", - "new-password-again": "Nueva contraseña otra vez", - "password-link-sent-message": "El enlace para el restablecimieneto de la contraseña fue enviado exitosamente!", + "new-password-again": "Repita la nueva contraseña", + "password-link-sent-message": "¡El enlace para el restablecer la contraseña fue enviado correctamente!", "email": "Correo electrónico" }, "position": { @@ -1141,7 +1165,7 @@ }, "from-relations": "Relaciones salientes", "to-relations": "Relaciones entrantes", - "selected-relations": "{ count, plural, 1 {1 relation} other {# relations} } selecciondas", + "selected-relations": "{ count, plural, 1 {1 relación} other {# relaciones} } selecciondas", "type": "Tipo", "to-entity-type": "Hacia tipo de entidad", "to-entity-name": "Hacia nombre de entidad", @@ -1156,13 +1180,13 @@ "add": "Agregar relación", "edit": "Editar relación", "delete-to-relation-title": "¿Está seguro de que desea eliminar la relación hacia la entidad '{{entityName}}'?", - "delete-to-relation-text": "Tener cuidado, después de la confirmación, la entidad '{{entityName}}' no estará relacionada desde la entidad actual.", - "delete-to-relations-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 relation} other {# relations} }?", - "delete-to-relations-text": "Tener cuidado, después de la confirmación, se eliminarán todas las relaciones seleccionadas y las entidades correspondientes no estarán relacionadas desde la entidad actual.", + "delete-to-relation-text": "¡Cuidado! Después de la confirmación, la entidad '{{entityName}}' no estará relacionada desde la entidad actual.", + "delete-to-relations-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 relación} other {# relaciones} }?", + "delete-to-relations-text": "¡Cuidado! Después de la confirmación, se eliminarán todas las relaciones seleccionadas y las entidades correspondientes no estarán relacionadas desde la entidad actual.", "delete-from-relation-title": "¿Está seguro de que desea eliminar la relación desde la entidad '{{entityName}}'?", - "delete-from-relation-text": "Tener cuidado, después de la confirmación, la entidad actual no será relacionada desde la entidad '{{entityName}}'.", - "delete-from-relations-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 relation} other {# relations} }?", - "delete-from-relations-text": "Tener cuidado, después de la confirmación, se eliminarán todas las relaciones seleccionadas y la entidad actual no será relacionada desde las correspondientes entidades.", + "delete-from-relation-text": "¡Cuidado! Después de la confirmación, la entidad actual no será relacionada desde la entidad '{{entityName}}'.", + "delete-from-relations-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 relación} other {# relaciones} }?", + "delete-from-relations-text": "¡Cuidado! Después de la confirmación, se eliminarán todas las relaciones seleccionadas y la entidad actual no será relacionada desde las correspondientes entidades.", "remove-relation-filter": "Eliminar filtro de relación", "add-relation-filter": "Agregar filtro de relación", "any-relation": "Alguna relación", @@ -1183,10 +1207,10 @@ "set-root-rulechain-title": "¿Está seguro de que desea hacer la cadena de reglas '{{ruleChainName}}' root?", "set-root-rulechain-text": "Después de la confirmación, la cadena de reglas se volverá raíz y manejará todos los mensajes de transporte entrantes.", "delete-rulechain-title": "¿Está seguro de que desea eliminar la cadena de reglas '{{ruleChainName}}'?", - "delete-rulechain-text": "Tener cuidado, después de la confirmación, la cadena de reglas y todos los datos relacionados se volverán irrecuperables.", - "delete-rulechains-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 rule chain} other {# rule chains} }?", - "delete-rulechains-action-title": "Eliminar { count, plural, 1 {1 rule chain} other {# rule chains} }", - "delete-rulechains-text": "Tener cuidado, después de la confirmación se eliminarán todas las cadenas de reglas seleccionadas y todos los datos relacionados se volverán irrecuperables.", + "delete-rulechain-text": "¡Cuidado! Después de la confirmación, la cadena de reglas y todos los datos relacionados serán irrecuperables.", + "delete-rulechains-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 cadena de reglas} other {# cadenas de reglas} }?", + "delete-rulechains-action-title": "Eliminar { count, plural, 1 {1 cadena de reglas} other {# cadenas de reglas} }", + "delete-rulechains-text": "¡Cuidado! Después de la confirmación se eliminarán todas las cadenas de reglas seleccionadas y todos los datos relacionados serán irrecuperables.", "add-rulechain-text": "Agregar nueva cadena de reglas", "no-rulechains-text": "Cadenas de reglas no encontradas", "rulechain-details": "Detalles de la cadena de reglas", @@ -1211,7 +1235,7 @@ "details": "Detalles", "events": "Eventos", "search": "Nodos de búsqueda", - "open-node-library": "Abrir libreria de nodos", + "open-node-library": "Abrir librería de nodos", "add": "Agregar nodo de reglas", "name": "Nombre", "name-required": "El nombre es requerido.", @@ -1237,7 +1261,7 @@ "custom-link-label-required": "Etiqueta del enlace personalizado es requerida.", "link-labels": "Etiquetas del enlace", "link-labels-required": "Etiquetas del enlace son requeridas.", - "no-link-labels-found": "Etiquetas de enlaces no encontradas", + "no-link-labels-found": "No se encontraron etiquetas de enlaces", "no-link-label-matching": "'{{label}}' no encontrada.", "create-new-link-label": "Crear una nueva!", "type-filter": "Filtro", @@ -1258,7 +1282,7 @@ "type-unknown-details": "Regla de nodo no resuelta", "directive-is-not-loaded": "La directiva de configuración definida '{{directiveName}}' no está disponible.", "ui-resources-load-error": "Error al cargar los recursos de configuración ui.", - "invalid-target-rulechain": "No se puede resolver la cadena de reglas objetivo!", + "invalid-target-rulechain": "¡No se puede resolver la cadena de reglas objetivo!", "test-script-function": "Probar función script", "message": "Mensaje", "message-type": "Tipo de mensaje", @@ -1274,7 +1298,7 @@ "tenant": "Organización", "tenants": "Organizaciones", "management": "Gestión de la organización", - "add": "Agregar Organización", + "add": "Agregar organización", "admins": "Administradores", "manage-tenant-admins": "Gestionar administradores de la organización", "delete": "Eliminar organización", @@ -1282,10 +1306,10 @@ "no-tenants-text": "Organizaciones no encontradas", "tenant-details": "Detalles de la organización", "delete-tenant-title": "¿Está seguro de que desea eliminar la organización '{{tenantTitle}}'?", - "delete-tenant-text": "Tener cuidado, después de la confirmación, la organización y todos los datos relacionados se volverán irrecuperables.", - "delete-tenants-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 tenant} other {# tenants} }?", - "delete-tenants-action-title": "Eliminar { count, plural, 1 {1 tenant} other {# tenants} }", - "delete-tenants-text": "Tener cuidado, después de la confirmación se eliminarán todas las organizaciones seleccionadas y todos los datos relacionados se volverán irrecuperables.", + "delete-tenant-text": "¡Cuidado! Después de la confirmación, la organización y todos los datos relacionados serán irrecuperables.", + "delete-tenants-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 organización} other {# organizaciones} }?", + "delete-tenants-action-title": "Eliminar { count, plural, 1 {1 organización} other {# organizaciones} }", + "delete-tenants-text": "¡Cuidado! Después de la confirmación se eliminarán todas las organizaciones seleccionadas y todos los datos relacionados serán irrecuperables.", "title": "Título", "title-required": "Título es requerido.", "description": "Descripción", @@ -1294,14 +1318,14 @@ "copyId": "Copiar ID de la organización", "idCopiedMessage": "ID de la organización ha sido copiado al portapapeles", "select-tenant": "Seleccionar organización", - "no-tenants-matching": "Organizaciones que coincidan con '{{entity}}' no fueron encontradas.", + "no-tenants-matching": "No se encontraron organizaciones que coincidan con '{{entity}}'.", "tenant-required": "Organización es requerida" }, "timeinterval": { - "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }", - "minutes-interval": "{ minutes, plural, 1 {1 minute} other {# minutes} }", - "hours-interval": "{ hours, plural, 1 {1 hour} other {# hours} }", - "days-interval": "{ days, plural, 1 {1 day} other {# days} }", + "seconds-interval": "{ seconds, plural, 1 {1 segundo} other {# segundos} }", + "minutes-interval": "{ minutes, plural, 1 {1 minuto} other {# minutos} }", + "hours-interval": "{ hours, plural, 1 {1 hora} other {# horas} }", + "days-interval": "{ days, plural, 1 {1 día} other {# días} }", "days": "Días", "hours": "Horas", "minutes": "Minutos", @@ -1309,17 +1333,17 @@ "advanced": "Avanzado" }, "timewindow": { - "days": "{ days, plural, 1 { day } other {# days } }", - "hours": "{ hours, plural, 0 { hour } 1 {1 hour } other {# hours } }", - "minutes": "{ minutes, plural, 0 { minute } 1 {1 minute } other {# minutes } }", - "seconds": "{ seconds, plural, 0 { second } 1 {1 second } other {# seconds } }", + "days": "{ days, plural, 1 { día } other {# días } }", + "hours": "{ hours, plural, 0 { horas } 1 {1 hora } other {# horas } }", + "minutes": "{ minutes, plural, 0 { minutos } 1 {1 minuto } other {# minutos } }", + "seconds": "{ seconds, plural, 0 { segundos } 1 {1 segundo } other {# segundos } }", "realtime": "Tiempo real", "history": "Historia", - "last-prefix": "última", - "period": "desde {{ startTime }} to {{ endTime }}", - "edit": "Editat ventana de tiempo", + "last-prefix": "último(s)", + "period": "desde {{ startTime }} hasta {{ endTime }}", + "edit": "Editar ventana de tiempo", "date-range": "Rango de fecha", - "last": "Última", + "last": "Último(s)", "time-period": "Período de tiempo" }, "user": { @@ -1334,14 +1358,14 @@ "add": "Agregar Usuario", "delete": "Eliminar usuario", "add-user-text": "Agregar nuevo usuario", - "no-users-text": "Usuarios no encontrados", + "no-users-text": "No se encontraron usuarios", "user-details": "Detalles de usuario", "delete-user-title": "¿Está seguro de que desea eliminar el usuario '{{userEmail}}'?", - "delete-user-text": "Tener cuidado, después de la confirmación, el usuario y todos los datos relacionados se volverán irrecuperables.", - "delete-users-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 user} other {# users} }?", - "delete-users-action-title": "Delete { count, plural, 1 {1 user} other {# users} }", - "delete-users-text": "Tener cuidado, después de la confirmación se eliminarán todas los usuarios seleccionados y todos los datos relacionados se volverán irrecuperables.", - "activation-email-sent-message": "Correo electrónico de activación fue enviado exitosamente!", + "delete-user-text": "¡Cuidado! Después de la confirmación, el usuario y todos los datos relacionados serán irrecuperables.", + "delete-users-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 usuario} other {# usuarios} }?", + "delete-users-action-title": "Borrar { count, plural, 1 {1 usuario} other {# usuarios} }", + "delete-users-text": "¡Cuidado! Después de la confirmación se eliminarán todas los usuarios seleccionados y todos los datos relacionados serán irrecuperables.", + "activation-email-sent-message": "¡Correo electrónico de activación fue enviado correctamente!", "resend-activation": "Reenviar activación", "email": "Correo electrónico", "email-required": "Correo electrónico es requerido.", @@ -1358,12 +1382,12 @@ "display-activation-link": "Mostrar enlace de activación", "send-activation-mail": "Enviar correo electrónico de activación", "activation-link": "Enlace de activación de usuario", - "activation-link-text": "Para activar el usuario, utilizar los siguientes activation link :", + "activation-link-text": "Para activar el usuario, utilice el siguiente enlace de activación :", "copy-activation-link": "Copiar enlace de activación", "activation-link-copied-message": "El enlace de activación de usuario ha sido copiado al portapapeles", "details": "Detalles", "login-as-tenant-admin": "Iniciar sesión como Administrador de la Organización", - "login-as-customer-user": "Iniciar sesión como Usuario Cliente" + "login-as-customer-user": "Iniciar sesión como Usuario cliente" }, "value": { "type": "Tipo de valor", @@ -1381,32 +1405,32 @@ "long": "Largo" }, "widget": { - "widget-library": "Libreria de Widgets", - "widget-bundle": "Paquete de Widgets", + "widget-library": "Librería de widgets", + "widget-bundle": "Paquete de widgets", "select-widgets-bundle": "Seleccionar paquete de widgets", "management": "Gestión de widget", "editor": "Editor de Widget", - "widget-type-not-found": "Problema cargando configuración de widget.
Probablemente tipo de widget asociado fue eliminado.", + "widget-type-not-found": "Problema cargando configuración de widget.
Probablemente el tipo de widget asociado fue eliminado.", "widget-type-load-error": "El widget no fue cargado debido a los siguientes errores:", "remove": "Eliminar widget", "edit": "Editar widget", "remove-widget-title": "¿Está seguro de que desea eliminar el widget '{{widgetTitle}}'?", - "remove-widget-text": "Después de la confirmación, el widget y todos los datos relacionados se volverán irrecuperables.", + "remove-widget-text": "Después de la confirmación, el widget y todos los datos relacionados serán irrecuperables.", "timeseries": "Series temporales", "search-data": "Buscar datos", - "no-data-found": "Datos no encontrados", + "no-data-found": "No se encontraron datos", "latest-values": "Últimos valores", "rpc": "Widget de control", "alarm": "Widget de alarma", "static": "Widget estático", "select-widget-type": "Seleccionar tipo de widget", - "missing-widget-title-error": "Título del widget debe ser especificado!", + "missing-widget-title-error": "¡Título del widget debe ser especificado!", "widget-saved": "Widget guardado", - "unable-to-save-widget-error": "No se puede guardar widget! El widget tiene errores!", + "unable-to-save-widget-error": "¡No se puede guardar widget! ¡El widget tiene errores!", "save": "Guardar widget", "saveAs": "Guardar widget como", "save-widget-type-as": "Guardar tipo de widget como", - "save-widget-type-as-text": "Por favor ingresar nuevo título del widget y/o seleccionar paquete de widgets objetivo", + "save-widget-type-as-text": "Por favor escriba el nuevo título del widget y/o seleccionar paquete de widgets objetivo", "toggle-fullscreen": "Alternar pantalla completa", "run": "Ejecutar widget", "title": "Título del widget", @@ -1415,20 +1439,20 @@ "resources": "Recursos", "resource-url": "JavaScript/CSS URL", "remove-resource": "Eliminar recurso", - "add-resource": "Agregar recursose", + "add-resource": "Agregar recurso", "html": "HTML", - "tidy": "Ordenado", + "tidy": "Formatear", "css": "CSS", "settings-schema": "Esquema de configuración", "datakey-settings-schema": "Esquema de configuración de clave de datos", "javascript": "Javascript", "remove-widget-type-title": "¿Está seguro de que desea eliminar el tipo de widget '{{widgetName}}'?", - "remove-widget-type-text": "Después de la confirmación, el tipo de widget y todos los datos relacionados se volverán irrecuperables.", + "remove-widget-type-text": "Después de la confirmación, el tipo de widget y todos los datos relacionados serán irrecuperables.", "remove-widget-type": "Eliminar tipo de widget", "add-widget-type": "Agregar nuevo tipo de widget", - "widget-type-load-failed-error": "Failed to load widget type!", - "widget-template-load-failed-error": "Error al cargar la plantilla del widget!", - "add": "Agregar Widget", + "widget-type-load-failed-error": "¡Error al cargar el tipo de widget!", + "widget-template-load-failed-error": "¡Error al cargar la plantilla del widget!", + "add": "Agregar widget", "undo": "Deshacer cambios en el widget", "export": "Exportar widget" }, @@ -1446,21 +1470,21 @@ }, "widgets-bundle": { "current": "Paquete actual", - "widgets-bundles": "Paquetes de Widgets", - "add": "Agregar Paquete de Widgets", - "delete": "Eliminar paquete de widget", + "widgets-bundles": "Paquetes de widgets", + "add": "Agregar paquete de widgets", + "delete": "Eliminar paquete de widgets", "title": "Título", "title-required": "Título es requerido.", "add-widgets-bundle-text": "Agregar nuevo paquete de widgets", - "no-widgets-bundles-text": "Paquetes de widgets no encontrados", + "no-widgets-bundles-text": "No se encontraron paquetes de widgets", "empty": "Paquete de widgets está vacío", "details": "Detalles", "widgets-bundle-details": "Detalles del paquete de widgets", "delete-widgets-bundle-title": "¿Está seguro de que desea eliminar el paquete de widgets '{{widgetsBundleTitle}}'?", - "delete-widgets-bundle-text": "Tener cuidado, después de la confirmación, el paquete de widgets y todos los datos relacionados se volverán irrecuperables.", - "delete-widgets-bundles-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 widgets bundle} other {# widgets bundles} }?", - "delete-widgets-bundles-action-title": "Eliminar { count, plural, 1 {1 widgets bundle} other {# widgets bundles} }", - "delete-widgets-bundles-text": "Tener cuidado, después de la confirmación se eliminarán todas los paquetes de widgets seleccionados y todos los datos relacionados se volverán irrecuperables.", + "delete-widgets-bundle-text": "¡Cuidado! Después de la confirmación, el paquete de widgets y todos los datos relacionados serán irrecuperables.", + "delete-widgets-bundles-title": "¿Está seguro de que desea eliminar { count, plural, 1 {1 paquete de widgets} other {# paquetes de widgets} }?", + "delete-widgets-bundles-action-title": "Eliminar { count, plural, 1 {1 paquete de widgets} other {# paquetes de widgets} }", + "delete-widgets-bundles-text": "¡Cuidado! Después de la confirmación se eliminarán todas los paquetes de widgets seleccionados y todos los datos relacionados serán irrecuperables.", "no-widgets-bundles-matching": "Paquetes de widgets que coincidan con '{{widgetsBundle}}' no fueron encontrados.", "widgets-bundle-required": "Paquete de widgets es requerido.", "system": "Sistema", @@ -1492,25 +1516,25 @@ "units": "Símbolo especial para mostrar junto al valor.", "decimals": "Número de dígitos después del punto flotante", "timewindow": "Ventana de tiempo", - "use-dashboard-timewindow": "Utilizar ventana de timpo del panel", + "use-dashboard-timewindow": "Utilizar ventana de tiempo del panel", "display-legend": "Mostrar leyenda", - "datasources": "Fuentes de datos", - "maximum-datasources": "Máximo { count, plural, 1 {1 datasource is allowed.} other {# datasources are allowed} }", + "datasources": "Orígenes de datos", + "maximum-datasources": "Máximo { count, plural, 1 {1 origen de datos permitido.} other {# origenes de datos permitidos} }", "datasource-type": "Tipo", - "datasource-parameters": "Parametros", - "remove-datasource": "Eliminar fuente de datos", - "add-datasource": "Agregar fuente de datos", + "datasource-parameters": "Parámetros", + "remove-datasource": "Eliminar origen de datos", + "add-datasource": "Agregar origen de datos", "target-device": "Dispositivo objetivo", - "alarm-source": "Fuente de alarma", - "actions": "Accines", + "alarm-source": "Origen de la alarma", + "actions": "Acciones", "action": "Acción", "add-action": "Agregar acción", "search-actions": "Buscar acciones", - "action-source": "Fuente de acción", + "action-source": "Origen de acción", "action-source-required": "Fuente de acción es requerida.", "action-name": "Nombre", "action-name-required": "Nombre de acción es requerido.", - "action-name-not-unique": "Ya existe otra acción con el mismo nombre.
El nombre de la acción debe ser único dentro de la misma fuente de acción.", + "action-name-not-unique": "Ya existe otra acción con el mismo nombre.
El nombre de la acción debe ser único dentro del mismo orígen de acción.", "action-icon": "Icono", "action-type": "Tipo", "action-type-required": "Tipo de acción es requerido.", @@ -1530,7 +1554,7 @@ "icon": { "icon": "Icono", "select-icon": "Seleccionar icono", - "material-icons": "Iconos de maerial", + "material-icons": "Iconos de material design", "show-all": "Mostrar todos los iconos" }, "custom": { From e375124b07a1a30a8a9ec19fe8263fdd1566ea84 Mon Sep 17 00:00:00 2001 From: Andrew Shvayka Date: Tue, 15 Jan 2019 12:43:25 +0200 Subject: [PATCH 25/27] Improved logging of Component Actor --- .../server/actors/service/ComponentActor.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/actors/service/ComponentActor.java b/application/src/main/java/org/thingsboard/server/actors/service/ComponentActor.java index 1f084e1bb7..6a53fd3714 100644 --- a/application/src/main/java/org/thingsboard/server/actors/service/ComponentActor.java +++ b/application/src/main/java/org/thingsboard/server/actors/service/ComponentActor.java @@ -16,9 +16,6 @@ package org.thingsboard.server.actors.service; import akka.actor.ActorRef; -import akka.event.Logging; -import akka.event.LoggingAdapter; -import lombok.extern.slf4j.Slf4j; import org.thingsboard.server.actors.ActorSystemContext; import org.thingsboard.server.actors.shared.ComponentMsgProcessor; import org.thingsboard.server.actors.stats.StatsPersistMsg; @@ -60,7 +57,8 @@ public abstract class ComponentActor getErrorPersistFrequency()) { From 5aced98ce38ea479f23e7da9b39a09dfeff1c92c Mon Sep 17 00:00:00 2001 From: Valerii Sosliuk Date: Wed, 16 Jan 2019 17:17:50 +0200 Subject: [PATCH 26/27] Fix NPE in Netty-mqtt client (#1398) * Fix NPE in netty-mqtt client on puback * Fix gateway mqtt extension configuration - filter is not required --- .../src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java | 3 +++ .../extension/extensions-forms/extension-form-mqtt.tpl.html | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java index c927c428e6..d2a1ad129e 100644 --- a/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java +++ b/netty-mqtt/src/main/java/org/thingsboard/mqtt/MqttChannelHandler.java @@ -222,6 +222,9 @@ final class MqttChannelHandler extends SimpleChannelInboundHandler private void handlePuback(MqttPubAckMessage message) { MqttPendingPublish pendingPublish = this.client.getPendingPublishes().get(message.variableHeader().messageId()); + if (pendingPublish == null) { + return; + } pendingPublish.getFuture().setSuccess(null); pendingPublish.onPubackReceived(); this.client.getPendingPublishes().remove(message.variableHeader().messageId()); diff --git a/ui/src/app/extension/extensions-forms/extension-form-mqtt.tpl.html b/ui/src/app/extension/extensions-forms/extension-form-mqtt.tpl.html index 9f0b547eef..6c0ab90e47 100644 --- a/ui/src/app/extension/extensions-forms/extension-form-mqtt.tpl.html +++ b/ui/src/app/extension/extensions-forms/extension-form-mqtt.tpl.html @@ -261,7 +261,7 @@ - +
extension.field-required
From 9d23930b19936a859387e44bc29ec2ba09b4d11c Mon Sep 17 00:00:00 2001 From: Valerii Sosliuk Date: Wed, 16 Jan 2019 17:20:38 +0200 Subject: [PATCH 27/27] Alarm node changed to read alarm config from message (#1396) * Alarm node changed to read alarm config from message * Alarm node changed to read alarm config from message * Alarm node changed to read alarm config from message --- .../rule/engine/action/TbCreateAlarmNode.java | 62 ++++++++++++++----- .../TbCreateAlarmNodeConfiguration.java | 2 + .../static/rulenode/rulenode-core-config.js | 8 +-- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java index a660c93caa..82a645c5c1 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNode.java @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.action; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; @@ -31,6 +32,8 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; +import java.io.IOException; + @Slf4j @RuleNode( type = ComponentType.ACTION, @@ -49,6 +52,8 @@ import org.thingsboard.server.common.msg.TbMsg; ) public class TbCreateAlarmNode extends TbAbstractAlarmNode { + private static ObjectMapper mapper = new ObjectMapper(); + @Override protected TbCreateAlarmNodeConfiguration loadAlarmNodeConfig(TbNodeConfiguration configuration) throws TbNodeException { return TbNodeUtils.convert(configuration, TbCreateAlarmNodeConfiguration.class); @@ -56,32 +61,59 @@ public class TbCreateAlarmNode extends TbAbstractAlarmNode processAlarm(TbContext ctx, TbMsg msg) { - ListenableFuture latest = ctx.getAlarmService().findLatestByOriginatorAndType(ctx.getTenantId(), msg.getOriginator(), config.getAlarmType()); - return Futures.transformAsync(latest, a -> { - if (a == null || a.getStatus().isCleared()) { - return createNewAlarm(ctx, msg); + String alarmType; + final Alarm msgAlarm; + + if (!config.isUseMessageAlarmData()) { + alarmType = config.getAlarmType(); + msgAlarm = null; + } else { + try { + msgAlarm = mapper.readValue(msg.getData(), Alarm.class); + msgAlarm.setTenantId(ctx.getTenantId()); + alarmType = msgAlarm.getType(); + } catch (IOException e) { + ctx.tellFailure(msg, e); + return null; + } + } + + ListenableFuture latest = ctx.getAlarmService().findLatestByOriginatorAndType(ctx.getTenantId(), msg.getOriginator(), alarmType); + return Futures.transformAsync(latest, existingAlarm -> { + if (existingAlarm == null || existingAlarm.getStatus().isCleared()) { + return createNewAlarm(ctx, msg, msgAlarm); } else { - return updateAlarm(ctx, msg, a); + return updateAlarm(ctx, msg, existingAlarm, msgAlarm); } }, ctx.getDbCallbackExecutor()); } - private ListenableFuture createNewAlarm(TbContext ctx, TbMsg msg) { - ListenableFuture asyncAlarm = Futures.transform(buildAlarmDetails(ctx, msg, null), - details -> buildAlarm(msg, details, ctx.getTenantId())); + private ListenableFuture createNewAlarm(TbContext ctx, TbMsg msg, Alarm msgAlarm) { + ListenableFuture asyncAlarm; + if (msgAlarm != null ) { + asyncAlarm = Futures.immediateCheckedFuture(msgAlarm); + } else { + asyncAlarm = Futures.transform(buildAlarmDetails(ctx, msg, null), + details -> buildAlarm(msg, details, ctx.getTenantId())); + } ListenableFuture asyncCreated = Futures.transform(asyncAlarm, alarm -> ctx.getAlarmService().createOrUpdateAlarm(alarm), ctx.getDbCallbackExecutor()); return Futures.transform(asyncCreated, alarm -> new AlarmResult(true, false, false, alarm)); } - private ListenableFuture updateAlarm(TbContext ctx, TbMsg msg, Alarm alarm) { - ListenableFuture asyncUpdated = Futures.transform(buildAlarmDetails(ctx, msg, alarm.getDetails()), (Function) details -> { - alarm.setSeverity(config.getSeverity()); - alarm.setPropagate(config.isPropagate()); - alarm.setDetails(details); - alarm.setEndTs(System.currentTimeMillis()); - return ctx.getAlarmService().createOrUpdateAlarm(alarm); + private ListenableFuture updateAlarm(TbContext ctx, TbMsg msg, Alarm existingAlarm, Alarm msgAlarm) { + ListenableFuture asyncUpdated = Futures.transform(buildAlarmDetails(ctx, msg, existingAlarm.getDetails()), (Function) details -> { + if (msgAlarm != null) { + existingAlarm.setSeverity(msgAlarm.getSeverity()); + existingAlarm.setPropagate(msgAlarm.isPropagate()); + } else { + existingAlarm.setSeverity(config.getSeverity()); + existingAlarm.setPropagate(config.isPropagate()); + } + existingAlarm.setDetails(details); + existingAlarm.setEndTs(System.currentTimeMillis()); + return ctx.getAlarmService().createOrUpdateAlarm(existingAlarm); }, ctx.getDbCallbackExecutor()); return Futures.transform(asyncUpdated, a -> new AlarmResult(false, true, false, a)); diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java index b4247947ec..892ad2705e 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCreateAlarmNodeConfiguration.java @@ -24,6 +24,7 @@ public class TbCreateAlarmNodeConfiguration extends TbAbstractAlarmNodeConfigura private AlarmSeverity severity; private boolean propagate; + private boolean useMessageAlarmData; @Override public TbCreateAlarmNodeConfiguration defaultConfiguration() { @@ -36,6 +37,7 @@ public class TbCreateAlarmNodeConfiguration extends TbAbstractAlarmNodeConfigura configuration.setAlarmType("General Alarm"); configuration.setSeverity(AlarmSeverity.CRITICAL); configuration.setPropagate(false); + configuration.setUseMessageAlarmData(false); return configuration; } } diff --git a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js index 5f5ef5c5ea..53b5213e22 100644 --- a/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js +++ b/rule-engine/rule-engine-components/src/main/resources/public/static/rulenode/rulenode-core-config.js @@ -1,5 +1,5 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),r=e[t[0]];return function(e,t,i){r.apply(this,[e,t,i].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(89)},function(e,t){},1,1,1,1,function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
{{ 'tb.rulenode.create-customer-if-not-exists' | translate }}
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{scope.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
{{ severity.name | translate}}
tb.rulenode.alarm-severity-required
{{ 'tb.rulenode.propagate' | translate }}
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-type-pattern-required
tb.rulenode.entity-type-pattern-hint
{{ 'tb.rulenode.create-entity-if-not-exists' | translate }}
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.bootstrap-servers-required
tb.rulenode.min-retries-message
tb.rulenode.min-batch-size-bytes-message
tb.rulenode.min-linger-ms-message
tb.rulenode.min-buffer-memory-bytes-message
{{ ackValue }}
tb.rulenode.key-serializer-required
tb.rulenode.value-serializer-required
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-to-string-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.mqtt-topic-pattern-hint
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
tb.rulenode.connect-timeout-required
tb.rulenode.connect-timeout-range
tb.rulenode.connect-timeout-range
{{ \'tb.rulenode.clean-session\' | translate }} {{ \'tb.rulenode.enable-ssl\' | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{credentialsValue.name | translate}}
tb.rulenode.credentials-type-required
tb.rulenode.username-required
tb.rulenode.password-required
'},function(e,t){e.exports="
tb.rulenode.interval-seconds-required
tb.rulenode.min-interval-seconds-message
tb.rulenode.output-timeseries-key-prefix-required
"},function(e,t){e.exports="
tb.rulenode.period-seconds-required
tb.rulenode.min-period-0-seconds-message
tb.rulenode.max-pending-messages-required
tb.rulenode.max-pending-messages-range
tb.rulenode.max-pending-messages-range
"},function(e,t){e.exports='
{{ property }}
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
{{ \'tb.rulenode.automatic-recovery\' | translate }}
tb.rulenode.min-connection-timeout-ms-message
tb.rulenode.min-handshake-timeout-ms-message
'},function(e,t){e.exports='
tb.rulenode.endpoint-url-pattern-required
tb.rulenode.endpoint-url-pattern-hint
{{ type }}
tb.rulenode.headers-hint
'},function(e,t){e.exports="
"},function(e,t){e.exports="
tb.rulenode.timeout-required
tb.rulenode.min-timeout-message
"},function(e,t){e.exports='
{{ \'tb.rulenode.use-system-smtp-settings\' | translate }}
{{smtpProtocol.toUpperCase()}}
tb.rulenode.smtp-host-required
tb.rulenode.smtp-port-required
tb.rulenode.smtp-port-range
tb.rulenode.smtp-port-range
tb.rulenode.timeout-required
tb.rulenode.min-timeout-msec-message
{{ \'tb.rulenode.enable-tls\' | translate }}
'; -},function(e,t){e.exports="
tb.rulenode.topic-arn-pattern-required
tb.rulenode.topic-arn-pattern-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
"},function(e,t){e.exports='
{{ type.name | translate }}
tb.rulenode.queue-url-pattern-required
tb.rulenode.queue-url-pattern-hint
tb.rulenode.min-delay-seconds-message
tb.rulenode.max-delay-seconds-message
tb.rulenode.message-attributes-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
'},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{ (\'relation.search-direction.\' + direction) | translate}}
relation.relation-type
device.device-types
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports='
{{ type }} {{ \'tb.rulenode.use-metadata-interval-patterns\' | translate }}
tb.rulenode.start-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.end-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.start-interval-pattern-required
tb.rulenode.start-interval-pattern-hint
tb.rulenode.end-interval-pattern-required
tb.rulenode.end-interval-pattern-hint
'},function(e,t){e.exports='
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},28,function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
"},function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.from-template-required
tb.rulenode.from-template-hint
tb.rulenode.to-template-required
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.subject-template-required
tb.rulenode.subject-template-hint
tb.rulenode.body-template-required
tb.rulenode.body-template-hint
"},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(6),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(7),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n,r){var i=function(i,a,l,s){var u=o.default;a.html(u),i.types=n,i.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(i.configuration)}),s.$render=function(){i.configuration=s.$viewValue},i.testDetailsBuildJs=function(e){var n=angular.copy(i.configuration.alarmDetailsBuildJs);r.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}i.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(8),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n,r){var i=function(i,a,l,s){var u=o.default;a.html(u),i.types=n,i.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(i.configuration)}),s.$render=function(){i.configuration=s.$viewValue},i.testDetailsBuildJs=function(e){var n=angular.copy(i.configuration.alarmDetailsBuildJs);r.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],i.ruleNodeId).then(function(e){i.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(a.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}i.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(9),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(10),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(11),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n,r){var i=function(i,a,l,s){var u=o.default;a.html(u),i.types=n,i.originator=null,i.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(i.configuration)}),s.$render=function(){i.configuration=s.$viewValue,i.configuration.originatorId&&i.configuration.originatorType?i.originator={id:i.configuration.originatorId,entityType:i.configuration.originatorType}:i.originator=null,i.$watch("originator",function(e,t){angular.equals(e,t)||(i.originator?(s.$viewValue.originatorId=i.originator.id,s.$viewValue.originatorType=i.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},i.testScript=function(e){var n=angular.copy(i.configuration.jsScript);r.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],i.ruleNodeId).then(function(e){i.configuration.jsScript=e,s.$setDirty()})},e(a.contents())(i)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:i}}i.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i,n(1);var a=n(12),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(65),a=r(i),o=n(46),l=r(o),s=n(51),u=r(s),d=n(48),c=r(d),m=n(47),g=r(m),p=n(54),f=r(p),b=n(60),v=r(b),y=n(61),q=r(y),h=n(59),$=r(h),x=n(53),T=r(x),k=n(63),C=r(k),w=n(64),M=r(w),_=n(58),S=r(_),N=n(55),E=r(N),P=n(62),V=r(P),F=n(57),j=r(F),A=n(56),I=r(A),O=n(45),K=r(O),R=n(66),D=r(R),U=n(50),L=r(U),z=n(49),B=r(z); -t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTimeseriesConfig",a.default).directive("tbActionNodeAttributesConfig",l.default).directive("tbActionNodeGeneratorConfig",u.default).directive("tbActionNodeCreateAlarmConfig",c.default).directive("tbActionNodeClearAlarmConfig",g.default).directive("tbActionNodeLogConfig",f.default).directive("tbActionNodeRpcReplyConfig",v.default).directive("tbActionNodeRpcRequestConfig",q.default).directive("tbActionNodeRestApiCallConfig",$.default).directive("tbActionNodeKafkaConfig",T.default).directive("tbActionNodeSnsConfig",C.default).directive("tbActionNodeSqsConfig",M.default).directive("tbActionNodeRabbitMqConfig",S.default).directive("tbActionNodeMqttConfig",E.default).directive("tbActionNodeSendEmailConfig",V.default).directive("tbActionNodeMsgDelayConfig",j.default).directive("tbActionNodeMsgCountConfig",I.default).directive("tbActionNodeAssignToCustomerConfig",K.default).directive("tbActionNodeUnAssignToCustomerConfig",D.default).directive("tbActionNodeDeleteRelationConfig",L.default).directive("tbActionNodeCreateRelationConfig",B.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.ackValues=["all","-1","0","1"],t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(13),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var i=angular.copy(r.configuration.jsScript);n.testNodeScript(e,i,"string",t.instant("tb.rulenode.to-string")+"","ToString",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}i.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(14),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s),r.$mdExpansionPanel=t,r.ruleNodeTypes=n,r.credentialsTypeChanged=function(){var e=r.configuration.credentials.type;r.configuration.credentials={},r.configuration.credentials.type=e,r.updateValidity()},r.certFileAdded=function(e,t){var n=new FileReader;n.onload=function(n){r.$apply(function(){if(n.target.result){l.$setDirty();var i=n.target.result;i&&i.length>0&&("caCert"==t&&(r.configuration.credentials.caCertFileName=e.name,r.configuration.credentials.caCert=i),"privateKey"==t&&(r.configuration.credentials.privateKeyFileName=e.name,r.configuration.credentials.privateKey=i),"Cert"==t&&(r.configuration.credentials.certFileName=e.name,r.configuration.credentials.cert=i)),r.updateValidity()}})},n.readAsText(e.file)},r.clearCertFile=function(e){l.$setDirty(),"caCert"==e&&(r.configuration.credentials.caCertFileName=null,r.configuration.credentials.caCert=null),"privateKey"==e&&(r.configuration.credentials.privateKeyFileName=null,r.configuration.credentials.privateKey=null),"Cert"==e&&(r.configuration.credentials.certFileName=null,r.configuration.credentials.cert=null),r.updateValidity()},r.updateValidity=function(){var e=!0,t=r.configuration.credentials;t.type==n.mqttCredentialTypes["cert.PEM"].value&&(t.caCert&&t.cert&&t.privateKey||(e=!1)),l.$setValidity("Certs",e)},r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:r}}i.$inject=["$compile","$mdExpansionPanel","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i,n(2);var a=n(15),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(16),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(17),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"],t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(18),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(19),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(20),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(21),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.smtpProtocols=["smtp","smtps"],t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(22),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(23),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:n}}i.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(24),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(25),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(26),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(27),o=r(a)},function(e,t){"use strict";function n(e){var t=function(t,n,r,i){n.html("
"),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(28),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(29),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s);var u=186;r.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,u],r.ruleNodeTypes=n,r.aggPeriodTimeUnits={},r.aggPeriodTimeUnits.MINUTES=n.timeUnit.MINUTES,r.aggPeriodTimeUnits.HOURS=n.timeUnit.HOURS,r.aggPeriodTimeUnits.DAYS=n.timeUnit.DAYS,r.aggPeriodTimeUnits.MILLISECONDS=n.timeUnit.MILLISECONDS,r.aggPeriodTimeUnits.SECONDS=n.timeUnit.SECONDS,r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{},link:r}}i.$inject=["$compile","$mdConstant","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(30),o=r(a);n(3)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(73),a=r(i),o=n(74),l=r(o),s=n(70),u=r(s),d=n(75),c=r(d),m=n(69),g=r(m),p=n(76),f=r(p),b=n(71),v=r(b);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",a.default).directive("tbEnrichmentNodeOriginatorFieldsConfig",l.default).directive("tbEnrichmentNodeDeviceAttributesConfig",u.default).directive("tbEnrichmentNodeRelatedAttributesConfig",c.default).directive("tbEnrichmentNodeCustomerAttributesConfig",g.default).directive("tbEnrichmentNodeTenantAttributesConfig",f.default).directive("tbEnrichmentNodeGetTelemetryFromDatabase",v.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(31),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(32),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(33),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(34),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(35),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(81),a=r(i),o=n(79),l=r(o),s=n(82),u=r(s),d=n(77),c=r(d),m=n(80),g=r(m);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",a.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).directive("tbFilterNodeCheckRelationConfig",c.default).directive("tbFilterNodeOriginatorTypeConfig",g.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),i.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),i.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=i,t.removeKeyVal=a,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||i.$setViewValue(t.query)}),i.$render=function(){if(i.$viewValue){var e=i.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(40),o=r(a);n(5)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||a.$setViewValue(n.query)}),a.$render=function(){n.query=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(41),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t){var n=function(n,r,i,a){var l=o.default;r.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||a.$setViewValue(n.configuration)}),a.$render=function(){n.configuration=a.$viewValue},e(r.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}i.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(42),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(85),a=r(i),o=n(87),l=r(o),s=n(88),u=r(s);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",a.default).directive("tbTransformationNodeScriptConfig",l.default).directive("tbTransformationNodeToEmailConfig",u.default).name},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var r=function(r,i,a,l){var s=o.default;i.html(s),r.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(r.configuration)}),l.$render=function(){r.configuration=l.$viewValue},r.testScript=function(e){var i=angular.copy(r.configuration.jsScript);n.testNodeScript(e,i,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,l.$setDirty()})},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}i.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(43),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){var t=function(t,n,r,i){var a=o.default;n.html(a),t.$watch("configuration",function(e,n){angular.equals(e,n)||i.$setViewValue(t.configuration)}),i.$render=function(){t.configuration=i.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}i.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(44),o=r(a)},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var i=n(92),a=r(i),o=n(78),l=r(o),s=n(72),u=r(s),d=n(86),c=r(d),m=n(52),g=r(m),p=n(68),f=r(p),b=n(84),v=r(b),y=n(67),q=r(y),h=n(83),$=r(h),x=n(91),T=r(x);t.default=angular.module("thingsboard.ruleChain.config",[a.default,l.default,u.default,c.default,g.default]).directive("tbNodeEmptyConfig",f.default).directive("tbRelationsQueryConfig",v.default).directive("tbDeviceRelationsQueryConfig",q.default).directive("tbKvMapConfig",$.default).config(T.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{"create-entity-if-not-exists":"Create new entity if not exists","entity-name-pattern":"Name pattern","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern, use ${metaKeyName} to substitute variables from metadata","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","entity-type-pattern-hint":"Type pattern, use ${metaKeyName} to substitute variables from metadata","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","customer-cache-expiration":"Customers cache expiration time (sec)","customer-name-pattern-hint":"Customer name pattern, use ${metaKeyName} to substitute variables from metadata","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","start-interval":"Start Interval","end-interval":"End Interval","start-interval-time-unit":"Start Interval Time Unit","end-interval-time-unit":"End Interval Time Unit","fetch-mode":"Fetch mode","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Time value should be in a range from 1 to 2147483647'.","start-interval-value-required":"Start interval value is required.","end-interval-value-required":"End interval value is required.",filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","fields-mapping":"Fields mapping","fields-mapping-required":"At least one field mapping should be specified.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","from-template-hint":"From address template, use ${metaKeyName} to substitute variables from metadata","to-template":"To Template","to-template-required":"To Template is required","mail-address-list-template-hint":"Comma separated address list, use ${metaKeyName} to substitute variables from metadata","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","subject-template-hint":"Mail subject template, use ${metaKeyName} to substitute variables from metadata","body-template":"Body Template","body-template-required":"Body Template is required","body-template-hint":"Mail body template, use ${metaKeyName} to substitute variables from metadata","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","endpoint-url-pattern-hint":"HTTP URL address pattern, use ${metaKeyName} to substitute variables from metadata","request-method":"Request method",headers:"Headers","headers-hint":"Use ${metaKeyName} in header/value fields to substitute variables from metadata",header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","topic-pattern-required":"Topic pattern is required","mqtt-topic-pattern-hint":"MQTT topic pattern, use ${metaKeyName} to substitute variables from metadata","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes", -"min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","topic-arn-pattern-hint":"Topic ARN pattern, use ${metaKeyName} to substitute variables from metadata","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","queue-url-pattern-hint":"Queue URL pattern, use ${metaKeyName} to substitute variables from metadata","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","message-attributes":"Message attributes","message-attributes-hint":"Use ${metaKeyName} in name/value fields to substitute variables from metadata","connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"CA certificate file *","private-key":"Private key file *",cert:"Certificate file *","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-interval-patterns":"Use metadata interval patterns","start-interval-pattern":"Start interval pattern","end-interval-pattern":"End interval pattern","start-interval-pattern-required":"Start interval pattern is required","end-interval-pattern-required":"End interval pattern is required","start-interval-pattern-hint":"Start interval pattern, use ${metaKeyName} to substitute variables from metadata","end-interval-pattern-hint":"End interval pattern, use ${metaKeyName} to substitute variables from metadata","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required."},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};e.translations("en_US",t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function r(e){return e&&e.__esModule?e:{default:e}}function i(e){(0,o.default)(e)}i.$inject=["$translateProvider"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=i;var a=n(90),o=r(a)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}},fetchModeType:["FIRST","LAST","ALL"],httpRequestType:["GET","POST","PUT","DELETE"],sqsQueueType:{STANDARD:{name:"tb.rulenode.sqs-queue-standard",value:"STANDARD"},FIFO:{name:"tb.rulenode.sqs-queue-fifo",value:"FIFO"}},timeUnit:{MILLISECONDS:{value:"MILLISECONDS",name:"tb.rulenode.time-unit-milliseconds"},SECONDS:{value:"SECONDS",name:"tb.rulenode.time-unit-seconds"},MINUTES:{value:"MINUTES",name:"tb.rulenode.time-unit-minutes"},HOURS:{value:"HOURS",name:"tb.rulenode.time-unit-hours"},DAYS:{value:"DAYS",name:"tb.rulenode.time-unit-days"}},mqttCredentialTypes:{anonymous:{value:"anonymous",name:"tb.rulenode.credentials-anonymous"},basic:{value:"basic",name:"tb.rulenode.credentials-basic"},"cert.PEM":{value:"cert.PEM",name:"tb.rulenode.credentials-pem"}}}).name}])); +!function(e){function t(a){if(n[a])return n[a].exports;var r=n[a]={exports:{},id:a,loaded:!1};return e[a].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="/static/",t(0)}(function(e){for(var t in e)if(Object.prototype.hasOwnProperty.call(e,t))switch(typeof e[t]){case"function":break;case"object":e[t]=function(t){var n=t.slice(1),a=e[t[0]];return function(e,t,r){a.apply(this,[e,t,r].concat(n))}}(e[t]);break;default:e[t]=e[e[t]]}return e}([function(e,t,n){e.exports=n(89)},function(e,t){},1,1,1,1,function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
{{ 'tb.rulenode.create-customer-if-not-exists' | translate }}
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{scope.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
tb.rulenode.alarm-type-required
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-details-function' | translate }}
{{ 'tb.rulenode.use-message-alarm-data' | translate }}
tb.rulenode.alarm-type-required
{{ severity.name | translate}}
tb.rulenode.alarm-severity-required
{{ 'tb.rulenode.propagate' | translate }}
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-type-pattern-required
tb.rulenode.entity-type-pattern-hint
{{ 'tb.rulenode.create-entity-if-not-exists' | translate }}
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
tb.rulenode.entity-name-pattern-required
tb.rulenode.entity-name-pattern-hint
tb.rulenode.entity-cache-expiration-required
tb.rulenode.entity-cache-expiration-range
tb.rulenode.entity-cache-expiration-hint
"},function(e,t){e.exports="
tb.rulenode.message-count-required
tb.rulenode.min-message-count-message
tb.rulenode.period-seconds-required
tb.rulenode.min-period-seconds-message
{{ 'tb.rulenode.test-generator-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.bootstrap-servers-required
tb.rulenode.min-retries-message
tb.rulenode.min-batch-size-bytes-message
tb.rulenode.min-linger-ms-message
tb.rulenode.min-buffer-memory-bytes-message
{{ ackValue }}
tb.rulenode.key-serializer-required
tb.rulenode.value-serializer-required
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-to-string-function' | translate }}
"},function(e,t){e.exports='
tb.rulenode.topic-pattern-required
tb.rulenode.mqtt-topic-pattern-hint
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
tb.rulenode.connect-timeout-required
tb.rulenode.connect-timeout-range
tb.rulenode.connect-timeout-range
{{ \'tb.rulenode.clean-session\' | translate }} {{ \'tb.rulenode.enable-ssl\' | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{ \'tb.rulenode.credentials\' | translate }}
{{ ruleNodeTypes.mqttCredentialTypes[configuration.credentials.type].name | translate }}
{{credentialsValue.name | translate}}
tb.rulenode.credentials-type-required
tb.rulenode.username-required
tb.rulenode.password-required
'},function(e,t){e.exports="
tb.rulenode.interval-seconds-required
tb.rulenode.min-interval-seconds-message
tb.rulenode.output-timeseries-key-prefix-required
"},function(e,t){e.exports="
tb.rulenode.period-seconds-required
tb.rulenode.min-period-0-seconds-message
tb.rulenode.max-pending-messages-required
tb.rulenode.max-pending-messages-range
tb.rulenode.max-pending-messages-range
"},function(e,t){e.exports='
{{ property }}
tb.rulenode.host-required
tb.rulenode.port-required
tb.rulenode.port-range
tb.rulenode.port-range
{{ \'tb.rulenode.automatic-recovery\' | translate }}
tb.rulenode.min-connection-timeout-ms-message
tb.rulenode.min-handshake-timeout-ms-message
'},function(e,t){e.exports='
tb.rulenode.endpoint-url-pattern-required
tb.rulenode.endpoint-url-pattern-hint
{{ type }}
tb.rulenode.headers-hint
'},function(e,t){e.exports="
"},function(e,t){e.exports="
tb.rulenode.timeout-required
tb.rulenode.min-timeout-message
"},function(e,t){e.exports='
{{ \'tb.rulenode.use-system-smtp-settings\' | translate }}
{{smtpProtocol.toUpperCase()}}
tb.rulenode.smtp-host-required
tb.rulenode.smtp-port-required
tb.rulenode.smtp-port-range
tb.rulenode.smtp-port-range
tb.rulenode.timeout-required
tb.rulenode.min-timeout-msec-message
{{ \'tb.rulenode.enable-tls\' | translate }}
'; +},function(e,t){e.exports="
tb.rulenode.topic-arn-pattern-required
tb.rulenode.topic-arn-pattern-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
"},function(e,t){e.exports='
{{ type.name | translate }}
tb.rulenode.queue-url-pattern-required
tb.rulenode.queue-url-pattern-hint
tb.rulenode.min-delay-seconds-message
tb.rulenode.max-delay-seconds-message
tb.rulenode.message-attributes-hint
tb.rulenode.aws-access-key-id-required
tb.rulenode.aws-secret-access-key-required
tb.rulenode.aws-region-required
'},function(e,t){e.exports="
tb.rulenode.default-ttl-required
tb.rulenode.min-default-ttl-message
"},function(e,t){e.exports="
tb.rulenode.customer-name-pattern-required
tb.rulenode.customer-name-pattern-hint
tb.rulenode.customer-cache-expiration-required
tb.rulenode.customer-cache-expiration-range
tb.rulenode.customer-cache-expiration-hint
"},function(e,t){e.exports='
{{ (\'relation.search-direction.\' + direction) | translate}}
relation.relation-type
device.device-types
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},function(e,t){e.exports='
'},function(e,t){e.exports='
{{ type }} {{ \'tb.rulenode.use-metadata-interval-patterns\' | translate }}
tb.rulenode.start-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.end-interval-value-required
tb.rulenode.time-value-range
tb.rulenode.time-value-range
{{timeUnit.name | translate}}
tb.rulenode.start-interval-pattern-required
tb.rulenode.start-interval-pattern-hint
tb.rulenode.end-interval-pattern-required
tb.rulenode.end-interval-pattern-hint
'},function(e,t){e.exports='
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.latest-telemetry' | translate }}
"},28,function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
"},function(e,t){e.exports='
{{item}}
tb.rulenode.no-message-types-found
tb.rulenode.no-message-type-matching tb.rulenode.create-new-message-type
{{$chip.name}}
'},function(e,t){e.exports='
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-filter-function' | translate }}
"},function(e,t){e.exports="
{{ 'tb.rulenode.test-switch-function' | translate }}
"},function(e,t){e.exports='
{{ keyText }} {{ valText }}  
{{keyRequiredText}}
{{valRequiredText}}
{{ \'tb.key-val.remove-entry\' | translate }} close
{{ \'tb.key-val.add-entry\' | translate }} add {{ \'action.add\' | translate }}
'},function(e,t){e.exports="
{{ ('relation.search-direction.' + direction) | translate}}
relation.relation-filters
"},function(e,t){e.exports='
{{ source.name | translate}}
'},function(e,t){e.exports="
{{ 'tb.rulenode.test-transformer-function' | translate }}
"},function(e,t){e.exports="
tb.rulenode.from-template-required
tb.rulenode.from-template-hint
tb.rulenode.to-template-required
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.mail-address-list-template-hint
tb.rulenode.subject-template-required
tb.rulenode.subject-template-hint
tb.rulenode.body-template-required
tb.rulenode.body-template-hint
"},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(6),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(7),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,a){var r=function(r,i,l,s){var u=o.default;i.html(u),r.types=n,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue},r.testDetailsBuildJs=function(e){var n=angular.copy(r.configuration.alarmDetailsBuildJs);a.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(8),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,a){var r=function(r,i,l,s){var u=o.default;i.html(u),r.types=n,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue},r.testDetailsBuildJs=function(e){var n=angular.copy(r.configuration.alarmDetailsBuildJs);a.testNodeScript(e,n,"json",t.instant("tb.rulenode.details")+"","Details",["msg","metadata","msgType"],r.ruleNodeId).then(function(e){r.configuration.alarmDetailsBuildJs=e,s.$setDirty()})},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(9),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(10),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(11),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n,a){var r=function(r,i,l,s){var u=o.default;i.html(u),r.types=n,r.originator=null,r.$watch("configuration",function(e,t){angular.equals(e,t)||s.$setViewValue(r.configuration)}),s.$render=function(){r.configuration=s.$viewValue,r.configuration.originatorId&&r.configuration.originatorType?r.originator={id:r.configuration.originatorId,entityType:r.configuration.originatorType}:r.originator=null,r.$watch("originator",function(e,t){angular.equals(e,t)||(r.originator?(s.$viewValue.originatorId=r.originator.id,s.$viewValue.originatorType=r.originator.entityType):(s.$viewValue.originatorId=null,s.$viewValue.originatorType=null))},!0)},r.testScript=function(e){var n=angular.copy(r.configuration.jsScript);a.testNodeScript(e,n,"generate",t.instant("tb.rulenode.generator")+"","Generate",["prevMsg","prevMetadata","prevMsgType"],r.ruleNodeId).then(function(e){r.configuration.jsScript=e,s.$setDirty()})},e(i.contents())(r)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:r}}r.$inject=["$compile","$translate","types","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r,n(1);var i=n(12),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(65),i=a(r),o=n(46),l=a(o),s=n(51),u=a(s),d=n(48),c=a(d),m=n(47),g=a(m),p=n(54),f=a(p),b=n(60),v=a(b),y=n(61),q=a(y),h=n(59),$=a(h),x=n(53),T=a(x),k=n(63),C=a(k),w=n(64),M=a(w),_=n(58),S=a(_),N=n(55),E=a(N),P=n(62),V=a(P),F=n(57),j=a(F),A=n(56),I=a(A),O=n(45),D=a(O),K=n(66),R=a(K),U=n(50),L=a(U),z=n(49),B=a(z); +t.default=angular.module("thingsboard.ruleChain.config.action",[]).directive("tbActionNodeTimeseriesConfig",i.default).directive("tbActionNodeAttributesConfig",l.default).directive("tbActionNodeGeneratorConfig",u.default).directive("tbActionNodeCreateAlarmConfig",c.default).directive("tbActionNodeClearAlarmConfig",g.default).directive("tbActionNodeLogConfig",f.default).directive("tbActionNodeRpcReplyConfig",v.default).directive("tbActionNodeRpcRequestConfig",q.default).directive("tbActionNodeRestApiCallConfig",$.default).directive("tbActionNodeKafkaConfig",T.default).directive("tbActionNodeSnsConfig",C.default).directive("tbActionNodeSqsConfig",M.default).directive("tbActionNodeRabbitMqConfig",S.default).directive("tbActionNodeMqttConfig",E.default).directive("tbActionNodeSendEmailConfig",V.default).directive("tbActionNodeMsgDelayConfig",j.default).directive("tbActionNodeMsgCountConfig",I.default).directive("tbActionNodeAssignToCustomerConfig",D.default).directive("tbActionNodeUnAssignToCustomerConfig",R.default).directive("tbActionNodeDeleteRelationConfig",L.default).directive("tbActionNodeCreateRelationConfig",B.default).name},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.ackValues=["all","-1","0","1"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(13),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var a=function(a,r,i,l){var s=o.default;r.html(s),a.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(a.configuration)}),l.$render=function(){a.configuration=l.$viewValue},a.testScript=function(e){var r=angular.copy(a.configuration.jsScript);n.testNodeScript(e,r,"string",t.instant("tb.rulenode.to-string")+"","ToString",["msg","metadata","msgType"],a.ruleNodeId).then(function(e){a.configuration.jsScript=e,l.$setDirty()})},e(r.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:a}}r.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(14),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var a=function(a,r,i,l){var s=o.default;r.html(s),a.$mdExpansionPanel=t,a.ruleNodeTypes=n,a.credentialsTypeChanged=function(){var e=a.configuration.credentials.type;a.configuration.credentials={},a.configuration.credentials.type=e,a.updateValidity()},a.certFileAdded=function(e,t){var n=new FileReader;n.onload=function(n){a.$apply(function(){if(n.target.result){l.$setDirty();var r=n.target.result;r&&r.length>0&&("caCert"==t&&(a.configuration.credentials.caCertFileName=e.name,a.configuration.credentials.caCert=r),"privateKey"==t&&(a.configuration.credentials.privateKeyFileName=e.name,a.configuration.credentials.privateKey=r),"Cert"==t&&(a.configuration.credentials.certFileName=e.name,a.configuration.credentials.cert=r)),a.updateValidity()}})},n.readAsText(e.file)},a.clearCertFile=function(e){l.$setDirty(),"caCert"==e&&(a.configuration.credentials.caCertFileName=null,a.configuration.credentials.caCert=null),"privateKey"==e&&(a.configuration.credentials.privateKeyFileName=null,a.configuration.credentials.privateKey=null),"Cert"==e&&(a.configuration.credentials.certFileName=null,a.configuration.credentials.cert=null),a.updateValidity()},a.updateValidity=function(){var e=!0,t=a.configuration.credentials;t.type==n.mqttCredentialTypes["cert.PEM"].value&&(t.caCert&&t.cert&&t.privateKey||(e=!1)),l.$setValidity("Certs",e)},a.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(a.configuration)}),l.$render=function(){a.configuration=l.$viewValue},e(r.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:a}}r.$inject=["$compile","$mdExpansionPanel","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r,n(2);var i=n(15),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(16),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(17),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.messageProperties=[null,"BASIC","TEXT_PLAIN","MINIMAL_BASIC","MINIMAL_PERSISTENT_BASIC","PERSISTENT_BASIC","PERSISTENT_TEXT_PLAIN"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(18),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(19),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(20),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(21),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.smtpProtocols=["smtp","smtps"],t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(22),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(23),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{readonly:"=ngReadonly"},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(24),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(25),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(26),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(27),o=a(i)},function(e,t){"use strict";function n(e){var t=function(t,n,a,r){n.html("
"),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}n.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(28),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(29),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var a=function(a,r,i,l){var s=o.default;r.html(s);var u=186;a.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,u],a.ruleNodeTypes=n,a.aggPeriodTimeUnits={},a.aggPeriodTimeUnits.MINUTES=n.timeUnit.MINUTES,a.aggPeriodTimeUnits.HOURS=n.timeUnit.HOURS,a.aggPeriodTimeUnits.DAYS=n.timeUnit.DAYS,a.aggPeriodTimeUnits.MILLISECONDS=n.timeUnit.MILLISECONDS,a.aggPeriodTimeUnits.SECONDS=n.timeUnit.SECONDS,a.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(a.configuration)}),l.$render=function(){a.configuration=l.$viewValue},e(r.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{},link:a}}r.$inject=["$compile","$mdConstant","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(30),o=a(i);n(3)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(73),i=a(r),o=n(74),l=a(o),s=n(70),u=a(s),d=n(75),c=a(d),m=n(69),g=a(m),p=n(76),f=a(p),b=n(71),v=a(b);t.default=angular.module("thingsboard.ruleChain.config.enrichment",[]).directive("tbEnrichmentNodeOriginatorAttributesConfig",i.default).directive("tbEnrichmentNodeOriginatorFieldsConfig",l.default).directive("tbEnrichmentNodeDeviceAttributesConfig",u.default).directive("tbEnrichmentNodeRelatedAttributesConfig",c.default).directive("tbEnrichmentNodeCustomerAttributesConfig",g.default).directive("tbEnrichmentNodeTenantAttributesConfig",f.default).directive("tbEnrichmentNodeGetTelemetryFromDatabase",v.default).name},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l);var s=186;n.separatorKeys=[t.KEY_CODE.ENTER,t.KEY_CODE.COMMA,s],n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","$mdConstant"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(31),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(32),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(33),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(34),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(35),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(81),i=a(r),o=n(79),l=a(o),s=n(82),u=a(s),d=n(77),c=a(d),m=n(80),g=a(m);t.default=angular.module("thingsboard.ruleChain.config.filter",[]).directive("tbFilterNodeScriptConfig",i.default).directive("tbFilterNodeMessageTypeConfig",l.default).directive("tbFilterNodeSwitchConfig",u.default).directive("tbFilterNodeCheckRelationConfig",c.default).directive("tbFilterNodeOriginatorTypeConfig",g.default).name},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var a=function(a,r,i,l){function s(){if(l.$viewValue){for(var e=[],t=0;t-1&&t.kvList.splice(e,1)}function l(){t.kvList||(t.kvList=[]),t.kvList.push({key:"",value:""})}function s(){var e={};t.kvList.forEach(function(t){t.key&&(e[t.key]=t.value)}),r.$setViewValue(e),u()}function u(){var e=!0;t.required&&!t.kvList.length&&(e=!1),r.$setValidity("kvMap",e)}var d=o.default;n.html(d),t.ngModelCtrl=r,t.removeKeyVal=i,t.addKeyVal=l,t.kvList=[],t.$watch("query",function(e,n){angular.equals(e,n)||r.$setViewValue(t.query)}),r.$render=function(){if(r.$viewValue){var e=r.$viewValue;t.kvList.length=0;for(var n in e)t.kvList.push({key:n,value:e[n]})}t.$watch("kvList",function(e,t){angular.equals(e,t)||s()},!0),u()},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{required:"=ngRequired",disabled:"=ngDisabled",requiredText:"=",keyText:"=",keyRequiredText:"=",valText:"=",valRequiredText:"="},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(40),o=a(i);n(5)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.types=t,n.$watch("query",function(e,t){angular.equals(e,t)||i.$setViewValue(n.query)}),i.$render=function(){n.query=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","types"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(41),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t){var n=function(n,a,r,i){var l=o.default;a.html(l),n.ruleNodeTypes=t,n.$watch("configuration",function(e,t){angular.equals(e,t)||i.$setViewValue(n.configuration)}),i.$render=function(){n.configuration=i.$viewValue},e(a.contents())(n)};return{restrict:"E",require:"^ngModel",scope:{},link:n}}r.$inject=["$compile","ruleNodeTypes"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(42),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(85),i=a(r),o=n(87),l=a(o),s=n(88),u=a(s);t.default=angular.module("thingsboard.ruleChain.config.transform",[]).directive("tbTransformationNodeChangeOriginatorConfig",i.default).directive("tbTransformationNodeScriptConfig",l.default).directive("tbTransformationNodeToEmailConfig",u.default).name},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e,t,n){var a=function(a,r,i,l){var s=o.default;r.html(s),a.$watch("configuration",function(e,t){angular.equals(e,t)||l.$setViewValue(a.configuration)}),l.$render=function(){a.configuration=l.$viewValue},a.testScript=function(e){var r=angular.copy(a.configuration.jsScript);n.testNodeScript(e,r,"update",t.instant("tb.rulenode.transformer")+"","Transform",["msg","metadata","msgType"],a.ruleNodeId).then(function(e){a.configuration.jsScript=e,l.$setDirty()})},e(r.contents())(a)};return{restrict:"E",require:"^ngModel",scope:{ruleNodeId:"="},link:a}}r.$inject=["$compile","$translate","ruleNodeScriptTest"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(43),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){var t=function(t,n,a,r){var i=o.default;n.html(i),t.$watch("configuration",function(e,n){angular.equals(e,n)||r.$setViewValue(t.configuration)}),r.$render=function(){t.configuration=r.$viewValue},e(n.contents())(t)};return{restrict:"E",require:"^ngModel",scope:{},link:t}}r.$inject=["$compile"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(44),o=a(i)},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0});var r=n(92),i=a(r),o=n(78),l=a(o),s=n(72),u=a(s),d=n(86),c=a(d),m=n(52),g=a(m),p=n(68),f=a(p),b=n(84),v=a(b),y=n(67),q=a(y),h=n(83),$=a(h),x=n(91),T=a(x);t.default=angular.module("thingsboard.ruleChain.config",[i.default,l.default,u.default,c.default,g.default]).directive("tbNodeEmptyConfig",f.default).directive("tbRelationsQueryConfig",v.default).directive("tbDeviceRelationsQueryConfig",q.default).directive("tbKvMapConfig",$.default).config(T.default).name},function(e,t){"use strict";function n(e){var t={tb:{rulenode:{"create-entity-if-not-exists":"Create new entity if not exists","entity-name-pattern":"Name pattern","entity-name-pattern-required":"Name pattern is required","entity-name-pattern-hint":"Name pattern, use ${metaKeyName} to substitute variables from metadata","entity-type-pattern":"Type pattern","entity-type-pattern-required":"Type pattern is required","entity-type-pattern-hint":"Type pattern, use ${metaKeyName} to substitute variables from metadata","entity-cache-expiration":"Entities cache expiration time (sec)","entity-cache-expiration-hint":"Specifies maximum time interval allowed to store found entity records. 0 value means that records will never expire.","entity-cache-expiration-required":"Entities cache expiration time is required.","entity-cache-expiration-range":"Entities cache expiration time should be greater than or equal to 0.","customer-name-pattern":"Customer name pattern","customer-name-pattern-required":"Customer name pattern is required","create-customer-if-not-exists":"Create new customer if not exists","customer-cache-expiration":"Customers cache expiration time (sec)","customer-name-pattern-hint":"Customer name pattern, use ${metaKeyName} to substitute variables from metadata","customer-cache-expiration-hint":"Specifies maximum time interval allowed to store found customer records. 0 value means that records will never expire.","customer-cache-expiration-required":"Customers cache expiration time is required.","customer-cache-expiration-range":"Customers cache expiration time should be greater than or equal to 0.","start-interval":"Start Interval","end-interval":"End Interval","start-interval-time-unit":"Start Interval Time Unit","end-interval-time-unit":"End Interval Time Unit","fetch-mode":"Fetch mode","time-unit-milliseconds":"Milliseconds","time-unit-seconds":"Seconds","time-unit-minutes":"Minutes","time-unit-hours":"Hours","time-unit-days":"Days","time-value-range":"Time value should be in a range from 1 to 2147483647'.","start-interval-value-required":"Start interval value is required.","end-interval-value-required":"End interval value is required.",filter:"Filter",switch:"Switch","message-type":"Message type","message-type-required":"Message type is required.","message-types-filter":"Message types filter","no-message-types-found":"No message types found","no-message-type-matching":"'{{messageType}}' not found.","create-new-message-type":"Create a new one!","message-types-required":"Message types are required.","client-attributes":"Client attributes","shared-attributes":"Shared attributes","server-attributes":"Server attributes","latest-timeseries":"Latest timeseries","relations-query":"Relations query","device-relations-query":"Device relations query","max-relation-level":"Max relation level","unlimited-level":"Unlimited level","latest-telemetry":"Latest telemetry","attr-mapping":"Attributes mapping","source-attribute":"Source attribute","source-attribute-required":"Source attribute is required.","source-telemetry":"Source telemetry","source-telemetry-required":"Source telemetry is required.","target-attribute":"Target attribute","target-attribute-required":"Target attribute is required.","attr-mapping-required":"At least one attribute mapping should be specified.","fields-mapping":"Fields mapping","fields-mapping-required":"At least one field mapping should be specified.","source-field":"Source field","source-field-required":"Source field is required.","originator-source":"Originator source","originator-customer":"Customer","originator-tenant":"Tenant","originator-related":"Related","clone-message":"Clone message",transform:"Transform","default-ttl":"Default TTL in seconds","default-ttl-required":"Default TTL is required.","min-default-ttl-message":"Only 0 minimum TTL is allowed.","message-count":"Message count (0 - unlimited)","message-count-required":"Message count is required.","min-message-count-message":"Only 0 minimum message count is allowed.","period-seconds":"Period in seconds","period-seconds-required":"Period is required.","min-period-seconds-message":"Only 1 second minimum period is allowed.",originator:"Originator","message-body":"Message body","message-metadata":"Message metadata",generate:"Generate","test-generator-function":"Test generator function",generator:"Generator","test-filter-function":"Test filter function","test-switch-function":"Test switch function","test-transformer-function":"Test transformer function",transformer:"Transformer","alarm-create-condition":"Alarm create condition","test-condition-function":"Test condition function","alarm-clear-condition":"Alarm clear condition","alarm-details-builder":"Alarm details builder","test-details-function":"Test details function","alarm-type":"Alarm type","alarm-type-required":"Alarm type is required.","alarm-severity":"Alarm severity","alarm-severity-required":"Alarm severity is required",propagate:"Propagate",condition:"Condition",details:"Details","to-string":"To string","test-to-string-function":"Test to string function","from-template":"From Template","from-template-required":"From Template is required","from-template-hint":"From address template, use ${metaKeyName} to substitute variables from metadata","to-template":"To Template","to-template-required":"To Template is required","mail-address-list-template-hint":"Comma separated address list, use ${metaKeyName} to substitute variables from metadata","cc-template":"Cc Template","bcc-template":"Bcc Template","subject-template":"Subject Template","subject-template-required":"Subject Template is required","subject-template-hint":"Mail subject template, use ${metaKeyName} to substitute variables from metadata","body-template":"Body Template","body-template-required":"Body Template is required","body-template-hint":"Mail body template, use ${metaKeyName} to substitute variables from metadata","request-id-metadata-attribute":"Request Id Metadata attribute name","timeout-sec":"Timeout in seconds","timeout-required":"Timeout is required","min-timeout-message":"Only 0 minimum timeout value is allowed.","endpoint-url-pattern":"Endpoint URL pattern","endpoint-url-pattern-required":"Endpoint URL pattern is required","endpoint-url-pattern-hint":"HTTP URL address pattern, use ${metaKeyName} to substitute variables from metadata","request-method":"Request method",headers:"Headers","headers-hint":"Use ${metaKeyName} in header/value fields to substitute variables from metadata",header:"Header","header-required":"Header is required",value:"Value","value-required":"Value is required","topic-pattern":"Topic pattern","topic-pattern-required":"Topic pattern is required","mqtt-topic-pattern-hint":"MQTT topic pattern, use ${metaKeyName} to substitute variables from metadata","bootstrap-servers":"Bootstrap servers","bootstrap-servers-required":"Bootstrap servers value is required","other-properties":"Other properties",key:"Key","key-required":"Key is required",retries:"Automatically retry times if fails","min-retries-message":"Only 0 minimum retries is allowed.","batch-size-bytes":"Produces batch size in bytes","min-batch-size-bytes-message":"Only 0 minimum batch size is allowed.","linger-ms":"Time to buffer locally (ms)","min-linger-ms-message":"Only 0 ms minimum value is allowed.","buffer-memory-bytes":"Client buffer max size in bytes", +"min-buffer-memory-message":"Only 0 minimum buffer size is allowed.",acks:"Number of acknowledgments","key-serializer":"Key serializer","key-serializer-required":"Key serializer is required","value-serializer":"Value serializer","value-serializer-required":"Value serializer is required","topic-arn-pattern":"Topic ARN pattern","topic-arn-pattern-required":"Topic ARN pattern is required","topic-arn-pattern-hint":"Topic ARN pattern, use ${metaKeyName} to substitute variables from metadata","aws-access-key-id":"AWS Access Key ID","aws-access-key-id-required":"AWS Access Key ID is required","aws-secret-access-key":"AWS Secret Access Key","aws-secret-access-key-required":"AWS Secret Access Key is required","aws-region":"AWS Region","aws-region-required":"AWS Region is required","exchange-name-pattern":"Exchange name pattern","routing-key-pattern":"Routing key pattern","message-properties":"Message properties",host:"Host","host-required":"Host is required",port:"Port","port-required":"Port is required","port-range":"Port should be in a range from 1 to 65535.","virtual-host":"Virtual host",username:"Username",password:"Password","automatic-recovery":"Automatic recovery","connection-timeout-ms":"Connection timeout (ms)","min-connection-timeout-ms-message":"Only 0 ms minimum value is allowed.","handshake-timeout-ms":"Handshake timeout (ms)","min-handshake-timeout-ms-message":"Only 0 ms minimum value is allowed.","client-properties":"Client properties","queue-url-pattern":"Queue URL pattern","queue-url-pattern-required":"Queue URL pattern is required","queue-url-pattern-hint":"Queue URL pattern, use ${metaKeyName} to substitute variables from metadata","delay-seconds":"Delay (seconds)","min-delay-seconds-message":"Only 0 seconds minimum value is allowed.","max-delay-seconds-message":"Only 900 seconds maximum value is allowed.",name:"Name","name-required":"Name is required","queue-type":"Queue type","sqs-queue-standard":"Standard","sqs-queue-fifo":"FIFO","message-attributes":"Message attributes","message-attributes-hint":"Use ${metaKeyName} in name/value fields to substitute variables from metadata","connect-timeout":"Connection timeout (sec)","connect-timeout-required":"Connection timeout is required.","connect-timeout-range":"Connection timeout should be in a range from 1 to 200.","client-id":"Client ID","clean-session":"Clean session","enable-ssl":"Enable SSL",credentials:"Credentials","credentials-type":"Credentials type","credentials-type-required":"Credentials type is required.","credentials-anonymous":"Anonymous","credentials-basic":"Basic","credentials-pem":"PEM","username-required":"Username is required.","password-required":"Password is required.","ca-cert":"CA certificate file *","private-key":"Private key file *",cert:"Certificate file *","no-file":"No file selected.","drop-file":"Drop a file or click to select a file to upload.","private-key-password":"Private key password","use-system-smtp-settings":"Use system SMTP settings","use-metadata-interval-patterns":"Use metadata interval patterns","use-message-alarm-data":"Use message alarm data","start-interval-pattern":"Start interval pattern","end-interval-pattern":"End interval pattern","start-interval-pattern-required":"Start interval pattern is required","end-interval-pattern-required":"End interval pattern is required","start-interval-pattern-hint":"Start interval pattern, use ${metaKeyName} to substitute variables from metadata","end-interval-pattern-hint":"End interval pattern, use ${metaKeyName} to substitute variables from metadata","smtp-protocol":"Protocol","smtp-host":"SMTP host","smtp-host-required":"SMTP host is required.","smtp-port":"SMTP port","smtp-port-required":"You must supply a smtp port.","smtp-port-range":"SMTP port should be in a range from 1 to 65535.","timeout-msec":"Timeout ms","min-timeout-msec-message":"Only 0 ms minimum value is allowed.","enter-username":"Enter username","enter-password":"Enter password","enable-tls":"Enable TLS","min-period-0-seconds-message":"Only 0 second minimum period is allowed.","max-pending-messages":"Maximum pending messages","max-pending-messages-required":"Maximum pending messages is required.","max-pending-messages-range":"Maximum pending messages should be in a range from 1 to 100000.","originator-types-filter":"Originator types filter","interval-seconds":"Interval in seconds","interval-seconds-required":"Interval is required.","min-interval-seconds-message":"Only 1 second minimum interval is allowed.","output-timeseries-key-prefix":"Output timeseries key prefix","output-timeseries-key-prefix-required":"Output timeseries key prefix required."},"key-val":{key:"Key",value:"Value","remove-entry":"Remove entry","add-entry":"Add entry"}}};e.translations("en_US",t)}Object.defineProperty(t,"__esModule",{value:!0}),t.default=n},function(e,t,n){"use strict";function a(e){return e&&e.__esModule?e:{default:e}}function r(e){(0,o.default)(e)}r.$inject=["$translateProvider"],Object.defineProperty(t,"__esModule",{value:!0}),t.default=r;var i=n(90),o=a(i)},function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=angular.module("thingsboard.ruleChain.config.types",[]).constant("ruleNodeTypes",{originatorSource:{CUSTOMER:{name:"tb.rulenode.originator-customer",value:"CUSTOMER"},TENANT:{name:"tb.rulenode.originator-tenant",value:"TENANT"},RELATED:{name:"tb.rulenode.originator-related",value:"RELATED"}},fetchModeType:["FIRST","LAST","ALL"],httpRequestType:["GET","POST","PUT","DELETE"],sqsQueueType:{STANDARD:{name:"tb.rulenode.sqs-queue-standard",value:"STANDARD"},FIFO:{name:"tb.rulenode.sqs-queue-fifo",value:"FIFO"}},timeUnit:{MILLISECONDS:{value:"MILLISECONDS",name:"tb.rulenode.time-unit-milliseconds"},SECONDS:{value:"SECONDS",name:"tb.rulenode.time-unit-seconds"},MINUTES:{value:"MINUTES",name:"tb.rulenode.time-unit-minutes"},HOURS:{value:"HOURS",name:"tb.rulenode.time-unit-hours"},DAYS:{value:"DAYS",name:"tb.rulenode.time-unit-days"}},mqttCredentialTypes:{anonymous:{value:"anonymous",name:"tb.rulenode.credentials-anonymous"},basic:{value:"basic",name:"tb.rulenode.credentials-basic"},"cert.PEM":{value:"cert.PEM",name:"tb.rulenode.credentials-pem"}}}).name}])); //# sourceMappingURL=rulenode-core-config.js.map \ No newline at end of file