add opc-ua
This commit is contained in:
parent
8af217a9e8
commit
cc302f1801
@ -332,6 +332,20 @@ export default angular.module('thingsboard.types', [])
|
|||||||
toDouble: 'extension.to-double',
|
toDouble: 'extension.to-double',
|
||||||
custom: 'extension.custom'
|
custom: 'extension.custom'
|
||||||
},
|
},
|
||||||
|
extensionOpcSecurityTypes: {
|
||||||
|
Basic128Rsa15: "Basic128Rsa15",
|
||||||
|
Basic256: "Basic256",
|
||||||
|
Basic256Sha256: "Basic256Sha256",
|
||||||
|
None: "None"
|
||||||
|
},
|
||||||
|
extensionIdentityType: {
|
||||||
|
anonymous: "anonymous",
|
||||||
|
username: "username"
|
||||||
|
},
|
||||||
|
extensionKeystoreType: {
|
||||||
|
PKCS12: "PKCS12",
|
||||||
|
JKS: "JKS"
|
||||||
|
},
|
||||||
latestTelemetry: {
|
latestTelemetry: {
|
||||||
value: "LATEST_TELEMETRY",
|
value: "LATEST_TELEMETRY",
|
||||||
name: "attribute.scope-latest-telemetry",
|
name: "attribute.scope-latest-telemetry",
|
||||||
|
|||||||
@ -29,45 +29,72 @@ export default function ExtensionDialogController($scope, $mdDialog, $translate,
|
|||||||
vm.entityId = entityId;
|
vm.entityId = entityId;
|
||||||
vm.allExtensions = allExtensions;
|
vm.allExtensions = allExtensions;
|
||||||
|
|
||||||
vm.configuration = {};
|
|
||||||
vm.newExtension = {id:"",type:"",configuration:vm.configuration};
|
|
||||||
|
|
||||||
if(!vm.isAdd) {
|
if (extension) { // Editing
|
||||||
vm.newExtension = angular.copy(extension);
|
//vm.configuration = vm.extension.configuration;
|
||||||
vm.configuration = vm.newExtension.configuration;
|
vm.extension = angular.copy(extension);
|
||||||
editTransformers(vm.newExtension);
|
editTransformers(vm.extension);
|
||||||
|
} else { // Add new
|
||||||
|
vm.extension = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.cancel = cancel;
|
|
||||||
vm.save = save;
|
|
||||||
|
|
||||||
|
vm.extensionTypeChange = function () {
|
||||||
|
// $scope.theForm.$setPristine();
|
||||||
|
// $scope.theForm.$setUntouched();
|
||||||
|
|
||||||
|
if (vm.extension.type === "HTTP") {
|
||||||
|
vm.extension.configuration = {
|
||||||
|
"converterConfigurations": []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (vm.extension.type === "MQTT") {
|
||||||
|
vm.extension.configuration = {
|
||||||
|
"brokers": []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (vm.extension.type === "OPC UA") {
|
||||||
|
vm.extension.configuration = {
|
||||||
|
"servers": []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vm.cancel = cancel;
|
||||||
function cancel() {
|
function cancel() {
|
||||||
$mdDialog.cancel();
|
$mdDialog.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vm.save = save;
|
||||||
function save() {
|
function save() {
|
||||||
saveTransformers();
|
saveTransformers();
|
||||||
if(vm.isAdd) {
|
if(vm.isAdd) {
|
||||||
vm.allExtensions.push(vm.newExtension);
|
vm.allExtensions.push(vm.extension);
|
||||||
} else {
|
} else {
|
||||||
var index = vm.allExtensions.indexOf(extension);
|
var index = vm.allExtensions.indexOf(extension);
|
||||||
if(index > -1) {
|
if(index > -1) {
|
||||||
vm.allExtensions[index] = vm.newExtension;
|
vm.allExtensions[index] = vm.extension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var editedValue = angular.toJson(vm.allExtensions);
|
var editedValue = angular.toJson(vm.allExtensions);
|
||||||
|
|
||||||
attributeService.saveEntityAttributes(vm.entityType, vm.entityId, types.attributesScope.shared.value, [{key:"configuration", value:editedValue}]).then(
|
attributeService
|
||||||
function success() {
|
.saveEntityAttributes(
|
||||||
|
vm.entityType,
|
||||||
|
vm.entityId,
|
||||||
|
types.attributesScope.shared.value,
|
||||||
|
[{key:"configuration", value:editedValue}]
|
||||||
|
)
|
||||||
|
.then(function success() {
|
||||||
$scope.theForm.$setPristine();
|
$scope.theForm.$setPristine();
|
||||||
$mdDialog.hide();
|
$mdDialog.hide();
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.validateId = function() {
|
vm.validateId = function() {
|
||||||
var coincidenceArray = vm.allExtensions.filter(function(ext) {
|
var coincidenceArray = vm.allExtensions.filter(function(ext) {
|
||||||
return ext.id == vm.newExtension.id;
|
return ext.id == vm.extension.id;
|
||||||
});
|
});
|
||||||
if(coincidenceArray.length) {
|
if(coincidenceArray.length) {
|
||||||
if(!vm.isAdd) {
|
if(!vm.isAdd) {
|
||||||
@ -82,11 +109,11 @@ export default function ExtensionDialogController($scope, $mdDialog, $translate,
|
|||||||
} else {
|
} else {
|
||||||
$scope.theForm.extensionId.$setValidity('uniqueIdValidation', true);
|
$scope.theForm.extensionId.$setValidity('uniqueIdValidation', true);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function saveTransformers() {
|
function saveTransformers() {
|
||||||
var config = vm.newExtension.configuration.converterConfigurations;
|
var config = vm.extension.configuration.converterConfigurations;
|
||||||
if(vm.newExtension.type == types.extensionType.http) {
|
if(vm.extension.type == types.extensionType.http) {
|
||||||
for(let i=0;i<config.length;i++) {
|
for(let i=0;i<config.length;i++) {
|
||||||
for(let j=0;j<config[i].converters.length;j++){
|
for(let j=0;j<config[i].converters.length;j++){
|
||||||
for(let k=0;k<config[i].converters[j].attributes.length;k++){
|
for(let k=0;k<config[i].converters[j].attributes.length;k++){
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<md-dialog aria-label="{{ (vm.isAdd ? 'extension.add' : 'extension.edit' ) | translate }}" style="min-width: 1000px;">
|
<md-dialog class="extensionDialog" aria-label="{{ (vm.isAdd ? 'extension.add' : 'extension.edit' ) | translate }}">
|
||||||
<form name="theForm" ng-submit="vm.save()">
|
<form name="theForm" ng-submit="vm.save()">
|
||||||
<md-toolbar>
|
<md-toolbar>
|
||||||
<div class="md-toolbar-tools">
|
<div class="md-toolbar-tools">
|
||||||
@ -26,8 +26,11 @@
|
|||||||
</md-button>
|
</md-button>
|
||||||
</div>
|
</div>
|
||||||
</md-toolbar>
|
</md-toolbar>
|
||||||
|
|
||||||
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear>
|
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!loading" ng-show="loading"></md-progress-linear>
|
||||||
|
|
||||||
<span style="min-height: 5px;" flex="" ng-show="!loading"></span>
|
<span style="min-height: 5px;" flex="" ng-show="!loading"></span>
|
||||||
|
|
||||||
<md-dialog-content>
|
<md-dialog-content>
|
||||||
<div class="md-dialog-content">
|
<div class="md-dialog-content">
|
||||||
<md-content class="md-padding" layout="column">
|
<md-content class="md-padding" layout="column">
|
||||||
@ -35,41 +38,48 @@
|
|||||||
<section flex layout="row">
|
<section flex layout="row">
|
||||||
<md-input-container flex="60" class="md-block">
|
<md-input-container flex="60" class="md-block">
|
||||||
<label translate>extension.extension-id</label>
|
<label translate>extension.extension-id</label>
|
||||||
<input required name="extensionId" ng-model="vm.newExtension.id" ng-change="vm.validateId()">
|
<input required name="extensionId" ng-model="vm.extension.id" ng-change="vm.validateId()">
|
||||||
<div ng-messages="theForm.extensionId.$error">
|
<div ng-messages="theForm.extensionId.$error">
|
||||||
<div translate ng-message="required">extension.id-required</div>
|
<div translate ng-message="required">extension.id-required</div>
|
||||||
<div translate ng-message="uniqueIdValidation">extension.unique-id-required</div>
|
<div translate ng-message="uniqueIdValidation">extension.unique-id-required</div>
|
||||||
</div>
|
</div>
|
||||||
</md-input-container>
|
</md-input-container>
|
||||||
|
|
||||||
<md-input-container flex="40" class="md-block">
|
<md-input-container flex="40" class="md-block">
|
||||||
<label translate>extension.extension-type</label>
|
<label translate>extension.extension-type</label>
|
||||||
<md-select ng-disabled="!vm.isAdd" required name="extensionType" ng-model="vm.newExtension.type">
|
|
||||||
|
<md-select ng-disabled="!vm.isAdd" required name="extensionType" ng-change="vm.extensionTypeChange()" ng-model="vm.extension.type">
|
||||||
<md-option ng-repeat="(key,value) in vm.types.extensionType" ng-value="value">
|
<md-option ng-repeat="(key,value) in vm.types.extensionType" ng-value="value">
|
||||||
{{value}}
|
{{value}}
|
||||||
</md-option>
|
</md-option>
|
||||||
</md-select>
|
</md-select>
|
||||||
|
|
||||||
<div ng-messages="theForm.extensionType.$error">
|
<div ng-messages="theForm.extensionType.$error">
|
||||||
<div translate ng-message="required">extension.type-required</div>
|
<div translate ng-message="required">extension.type-required</div>
|
||||||
</div>
|
</div>
|
||||||
</md-input-container>
|
</md-input-container>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div tb-extension-form-http config="vm.configuration" is-add="vm.isAdd" ng-if="vm.newExtension.type && vm.newExtension.type == vm.types.extensionType.http"></div>
|
<div tb-extension-form-http config="vm.extension.configuration" is-add="vm.isAdd" ng-if="vm.extension.type && vm.extension.type == vm.types.extensionType.http"></div>
|
||||||
|
|
||||||
|
<div tb-extension-form-opc configuration="vm.extension.configuration" ng-if="vm.extension.type && vm.extension.type == vm.types.extensionType.opc"></div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
<!--<div>{{vm.extension}}</div>-->
|
||||||
<!--<div>{{vm.newExtension}}</div>-->
|
|
||||||
</md-content>
|
</md-content>
|
||||||
</div>
|
</div>
|
||||||
</md-dialog-content>
|
</md-dialog-content>
|
||||||
|
|
||||||
<md-dialog-actions layout="row">
|
<md-dialog-actions layout="row">
|
||||||
<span flex></span>
|
<span flex></span>
|
||||||
<md-button ng-disabled="loading || theForm.$invalid || !theForm.$dirty" type="submit"
|
<md-button type="submit"
|
||||||
|
ng-disabled="loading || theForm.$invalid || !theForm.$dirty"
|
||||||
class="md-raised md-primary">
|
class="md-raised md-primary">
|
||||||
{{ (vm.isAdd ? 'action.add' : 'action.save') | translate }}
|
{{ (vm.isAdd ? 'action.add' : 'action.save') | translate }}
|
||||||
</md-button>
|
</md-button>
|
||||||
|
|
||||||
<md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}
|
<md-button ng-disabled="loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}
|
||||||
</md-button>
|
</md-button>
|
||||||
</md-dialog-actions>
|
</md-dialog-actions>
|
||||||
</form>
|
</form>
|
||||||
</md-dialog>
|
</md-dialog>
|
||||||
|
|
||||||
|
|||||||
@ -126,11 +126,13 @@ function ExtensionTableController($scope, $filter, $document, $translate, types,
|
|||||||
controllerAs: 'vm',
|
controllerAs: 'vm',
|
||||||
templateUrl: extensionDialogTemplate,
|
templateUrl: extensionDialogTemplate,
|
||||||
parent: angular.element($document[0].body),
|
parent: angular.element($document[0].body),
|
||||||
locals: { isAdd: isAdd,
|
locals: {
|
||||||
|
isAdd: isAdd,
|
||||||
allExtensions: vm.allExtensions,
|
allExtensions: vm.allExtensions,
|
||||||
entityId: vm.entityId,
|
entityId: vm.entityId,
|
||||||
entityType: vm.entityType,
|
entityType: vm.entityType,
|
||||||
extension: extension},
|
extension: extension
|
||||||
|
},
|
||||||
bindToController: true,
|
bindToController: true,
|
||||||
targetEvent: $event,
|
targetEvent: $event,
|
||||||
fullscreen: true,
|
fullscreen: true,
|
||||||
|
|||||||
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2016-2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'brace/ext/language_tools';
|
||||||
|
import 'brace/mode/json';
|
||||||
|
import 'brace/theme/github';
|
||||||
|
|
||||||
|
import './extension-form.scss';
|
||||||
|
|
||||||
|
/* eslint-disable angular/log */
|
||||||
|
|
||||||
|
import extensionFormOpcTemplate from './extension-form-opc.tpl.html';
|
||||||
|
|
||||||
|
/* eslint-enable import/no-unresolved, import/default */
|
||||||
|
|
||||||
|
/*@ngInject*/
|
||||||
|
export default function ExtensionFormOpcDirective($compile, $templateCache, $translate, types) {
|
||||||
|
|
||||||
|
|
||||||
|
var linker = function(scope, element) {
|
||||||
|
|
||||||
|
|
||||||
|
function Server() {
|
||||||
|
this.applicationName = "Thingsboard OPC-UA client";
|
||||||
|
this.applicationUri = "";
|
||||||
|
this.host = "localhost";
|
||||||
|
this.port = 49320;
|
||||||
|
this.scanPeriodInSeconds = 10;
|
||||||
|
this.timeoutInMillis = 5000;
|
||||||
|
this.security = "Basic128Rsa15";
|
||||||
|
this.identity = {
|
||||||
|
"type": "anonymous"
|
||||||
|
};
|
||||||
|
this.keystore = {
|
||||||
|
"type": "PKCS12",
|
||||||
|
"location": "example.pfx",
|
||||||
|
"password": "secret",
|
||||||
|
"alias": "gateway",
|
||||||
|
"keyPassword": "secret"
|
||||||
|
};
|
||||||
|
this.mapping = []
|
||||||
|
}
|
||||||
|
|
||||||
|
function Map() {
|
||||||
|
this.deviceNodePattern = "Channel1\\.Device\\d+$";
|
||||||
|
this.deviceNamePattern = "Device ${_System._DeviceId}";
|
||||||
|
this.attributes = [];
|
||||||
|
this.timeseries = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function Attribute() {
|
||||||
|
this.key = "Tag1";
|
||||||
|
this.type = "string";
|
||||||
|
this.value = "${Tag1}";
|
||||||
|
}
|
||||||
|
|
||||||
|
function Timeseries() {
|
||||||
|
this.key = "Tag2";
|
||||||
|
this.type = "long";
|
||||||
|
this.value = "${Tag2}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var template = $templateCache.get(extensionFormOpcTemplate);
|
||||||
|
element.html(template);
|
||||||
|
|
||||||
|
scope.types = types;
|
||||||
|
scope.theForm = scope.$parent.theForm;
|
||||||
|
|
||||||
|
|
||||||
|
if (!scope.configuration.servers.length) {
|
||||||
|
scope.configuration.servers.push(new Server());
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.addServer = function(serversList) {
|
||||||
|
serversList.push(new Server());
|
||||||
|
// scope.addMap(serversList[serversList.length-1].mapping);
|
||||||
|
|
||||||
|
scope.theForm.$setDirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.addMap = function(mappingList) {
|
||||||
|
mappingList.push(new Map());
|
||||||
|
scope.theForm.$setDirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.addNewAttribute = function(attributesList) {
|
||||||
|
attributesList.push(new Attribute());
|
||||||
|
scope.theForm.$setDirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.addNewTimeseries = function(timeseriesList) {
|
||||||
|
timeseriesList.push(new Timeseries());
|
||||||
|
scope.theForm.$setDirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
scope.removeItem = (item, itemList) => {
|
||||||
|
var index = itemList.indexOf(item);
|
||||||
|
if (index > -1) {
|
||||||
|
itemList.splice(index, 1);
|
||||||
|
}
|
||||||
|
scope.theForm.$setDirty();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$compile(element.contents())(scope);
|
||||||
|
|
||||||
|
|
||||||
|
scope.fileAdded = function($file, model, options) {
|
||||||
|
let reader = new FileReader();
|
||||||
|
reader.onload = function(event) {
|
||||||
|
scope.$apply(function() {
|
||||||
|
if(event.target.result) {
|
||||||
|
scope.theForm.$setDirty();
|
||||||
|
let addedFile = event.target.result;
|
||||||
|
|
||||||
|
if (addedFile && addedFile.length > 0) {
|
||||||
|
model[options.fileName] = $file.name;
|
||||||
|
model[options.file] = addedFile.replace(/^data.*base64,/, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
reader.readAsDataURL($file.file);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
scope.clearFile = function(model, options) {
|
||||||
|
scope.theForm.$setDirty();
|
||||||
|
|
||||||
|
model[options.fileName] = null;
|
||||||
|
model[options.file] = null;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: "A",
|
||||||
|
link: linker,
|
||||||
|
scope: {
|
||||||
|
configuration: "=",
|
||||||
|
isAdd: "="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,4 +15,552 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<div>OPC UA</div>
|
<md-card class="extension-form extension-opc">
|
||||||
|
<md-card-title>
|
||||||
|
<md-card-title-text>
|
||||||
|
<span translate class="md-headline">extension.configuration</span>
|
||||||
|
</md-card-title-text>
|
||||||
|
</md-card-title>
|
||||||
|
|
||||||
|
<md-card-content>
|
||||||
|
<v-accordion id="http-server-configs-accordion" class="vAccordion--default">
|
||||||
|
<v-pane id="http-servers-pane" expanded="true">
|
||||||
|
<v-pane-header>
|
||||||
|
{{ 'extension.opc-server' | translate }}
|
||||||
|
</v-pane-header>
|
||||||
|
|
||||||
|
<v-pane-content>
|
||||||
|
<div ng-if="configuration.servers.length === 0">
|
||||||
|
<span translate layout-align="center center" class="tb-prompt">extension.opc-add-server-prompt</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="configuration.servers.length > 0">
|
||||||
|
<ol class="list-group">
|
||||||
|
<li class="list-group-item" ng-repeat="(serverIndex, server) in configuration.servers">
|
||||||
|
<md-button aria-label="{{ 'action.remove' | translate }}"
|
||||||
|
class="md-icon-button"
|
||||||
|
ng-click="removeItem(server, configuration.servers)"
|
||||||
|
ng-hide="configuration.servers.length < 2"
|
||||||
|
>
|
||||||
|
<ng-md-icon icon="close" aria-label="{{ 'action.remove' | translate }}"></ng-md-icon>
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'action.remove' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
</md-button>
|
||||||
|
|
||||||
|
<md-card>
|
||||||
|
<md-card-content>
|
||||||
|
|
||||||
|
<div layout="row">
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-application-name</label>
|
||||||
|
<input required name="applicationName_{{serverIndex}}" ng-model="server.applicationName">
|
||||||
|
<div ng-messages="theForm['applicationName_' + serverIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-application-uri</label>
|
||||||
|
<input required name="applicationUri_{{serverIndex}}" ng-model="server.applicationUri">
|
||||||
|
<div ng-messages="theForm['applicationUri_' + serverIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div layout="row">
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-host</label>
|
||||||
|
<input required name="host_{{serverIndex}}" ng-model="server.host">
|
||||||
|
<div ng-messages="theForm['host_' + serverIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-port</label>
|
||||||
|
<input type="number"
|
||||||
|
required
|
||||||
|
name="port_{{serverIndex}}"
|
||||||
|
ng-model="server.port"
|
||||||
|
min="1"
|
||||||
|
max="65535"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['port_' + serverIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
<div translate
|
||||||
|
ng-message="min"
|
||||||
|
>Port should be in a range from 1 to 65535</div>
|
||||||
|
<div translate
|
||||||
|
ng-message="max"
|
||||||
|
>Port should be in a range from 1 to 65535</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div layout="row">
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-scan-period-in-seconds</label>
|
||||||
|
<input type="number"
|
||||||
|
required
|
||||||
|
name="scanPeriodInSeconds_{{serverIndex}}"
|
||||||
|
ng-model="server.scanPeriodInSeconds">
|
||||||
|
<div ng-messages="theForm['scanPeriodInSeconds_' + serverIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-timeout-in-millis</label>
|
||||||
|
<input type="number"
|
||||||
|
required name="timeoutInMillis_{{serverIndex}}"
|
||||||
|
ng-model="server.timeoutInMillis"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['timeoutInMillis_' + serverIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div layout="row">
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block tb-container-for-select">
|
||||||
|
<label translate>extension.opc-security</label>
|
||||||
|
<md-select required
|
||||||
|
name="securityType_{{serverIndex}}"
|
||||||
|
ng-model="server.security">
|
||||||
|
<md-option ng-value="securityType"
|
||||||
|
ng-repeat="(securityType, securityValue) in types.extensionOpcSecurityTypes"
|
||||||
|
><span ng-bind="::securityValue"></span></md-option>
|
||||||
|
</md-select>
|
||||||
|
<div ng-messages="theForm['securityType_' + serverIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block tb-container-for-select">
|
||||||
|
<label translate>extension.opc-identity</label>
|
||||||
|
<md-select required
|
||||||
|
name="identityType_{{serverIndex}}"
|
||||||
|
ng-model="server.identity.type"
|
||||||
|
>
|
||||||
|
<md-option ng-value="identityType"
|
||||||
|
ng-repeat="(identityType, identityValue) in types.extensionIdentityType"
|
||||||
|
><span ng-bind="::identityValue"></span></md-option>
|
||||||
|
</md-select>
|
||||||
|
<div ng-messages="theForm['identityType_' + serverIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div ng-if="server.identity.type != 'username'">
|
||||||
|
<span class=""
|
||||||
|
ng-init="server.identity = {'type':'anonymous'}"></span>
|
||||||
|
</div>
|
||||||
|
<div layout="row" ng-if="server.identity.type == 'username'">
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-username</label>
|
||||||
|
<input required
|
||||||
|
name="identityUsername_{{serverIndex}}"
|
||||||
|
ng-model="server.identity.username"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['identityUsername_' + serverIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-password</label>
|
||||||
|
<input required
|
||||||
|
name="identityPassword_{{serverIndex}}" ng-model="server.identity.password">
|
||||||
|
<div ng-messages="theForm['identityPassword_' + serverIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<v-accordion id="opc-attributes-accordion" class="vAccordion--default">
|
||||||
|
<v-pane id="opc-attributes-pane">
|
||||||
|
<v-pane-header>
|
||||||
|
{{ 'extension.opc-keystore' | translate }}
|
||||||
|
</v-pane-header>
|
||||||
|
<v-pane-content>
|
||||||
|
|
||||||
|
<md-input-container class="md-block tb-container-for-select">
|
||||||
|
<label translate>extension.opc-keystore-type</label>
|
||||||
|
<md-select required name="keystoreType_{{serverIndex}}" ng-model="server.keystore.type">
|
||||||
|
<md-option ng-value="keystoreType" ng-repeat="(keystoreType, keystoreValue) in types.extensionKeystoreType"><span ng-bind="::keystoreValue"></span></md-option>
|
||||||
|
</md-select>
|
||||||
|
<div ng-messages="theForm['keystoreType_'+serverIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<div class="tb-container">
|
||||||
|
<span ng-init='fieldsToFill = {"fileName":"fileName", "file":"file"}'></span>
|
||||||
|
<label class="tb-label" translate>extension.opc-keystore-location</label>
|
||||||
|
<div flow-init="{singleFile:true}" flow-file-added='fileAdded($file, server.keystore, fieldsToFill)' class="tb-file-select-container">
|
||||||
|
<div class="tb-file-clear-container">
|
||||||
|
<md-button ng-click='clearFile(server.keystore, fieldsToFill)' class="tb-file-clear-btn md-icon-button md-primary" aria-label="{{ 'action.remove' | translate }}">
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'action.remove' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
<md-icon aria-label="{{ 'action.remove' | translate }}" class="material-icons">close</md-icon>
|
||||||
|
</md-button>
|
||||||
|
</div>
|
||||||
|
<div class="alert tb-flow-drop" flow-drop>
|
||||||
|
<label for="dropFileKeystore_{{serverIndex}}" translate>extension.drop-file</label>
|
||||||
|
<input flow-attrs="{accept:'.pfx,.p12'}"
|
||||||
|
type="file"
|
||||||
|
class="file-input"
|
||||||
|
flow-btn id="dropFileKeystore_{{serverIndex}}"
|
||||||
|
name="keystoreFile"
|
||||||
|
ng-model="server.keystore.file"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div ng-if="!server.keystore[fieldsToFill.fileName]" class="tb-error-message" translate>extension.no-file</div>
|
||||||
|
<div ng-if="server.keystore[fieldsToFill.fileName]">{{server.keystore[fieldsToFill.fileName]}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div flex layout="row">
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-keystore-password</label>
|
||||||
|
<input required name="keystorePassword_{{serverIndex}}" ng-model="server.keystore.password">
|
||||||
|
<div ng-messages="theForm['keystorePassword_' + serverIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-keystore-alias</label>
|
||||||
|
<input required name="keystoreAlias_{{serverIndex}}" ng-model="server.keystore.alias">
|
||||||
|
<div ng-messages="theForm['keystoreAlias_' + serverIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<md-input-container class="md-block">
|
||||||
|
<label translate>extension.opc-keystore-key-password</label>
|
||||||
|
<input required name="keystoreKeyPassword_{{serverIndex}}" ng-model="server.keystore.keyPassword">
|
||||||
|
<div ng-messages="theForm['keystoreKeyPassword_' + serverIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
</v-pane-content>
|
||||||
|
</v-pane>
|
||||||
|
</v-accordion>
|
||||||
|
|
||||||
|
|
||||||
|
<v-accordion id="opc-attributes-accordion"
|
||||||
|
class="vAccordion--default"
|
||||||
|
>
|
||||||
|
<v-pane id="opc-attributes-pane">
|
||||||
|
<v-pane-header>
|
||||||
|
{{ 'extension.opc-mapping' | translate }}
|
||||||
|
</v-pane-header>
|
||||||
|
<v-pane-content>
|
||||||
|
<div ng-if="server.mapping.length > 0">
|
||||||
|
<ol class="list-group">
|
||||||
|
<li class="list-group-item"
|
||||||
|
ng-repeat="(mapIndex, map) in server.mapping"
|
||||||
|
>
|
||||||
|
<md-button aria-label="{{ 'action.remove' | translate }}"
|
||||||
|
class="md-icon-button"
|
||||||
|
ng-click="removeItem(map, server.mapping)"
|
||||||
|
>
|
||||||
|
<ng-md-icon icon="close" aria-label="{{ 'action.remove' | translate }}"></ng-md-icon>
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'action.remove' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
</md-button>
|
||||||
|
|
||||||
|
<md-card>
|
||||||
|
<md-card-content>
|
||||||
|
<div flex layout="row">
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-device-node-pattern</label>
|
||||||
|
<input required
|
||||||
|
name="deviceNodePattern_{{serverIndex}}{{mapIndex}}"
|
||||||
|
ng-model="map.deviceNodePattern"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['deviceNodePattern_' + serverIndex + mapIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-input-container flex="50" class="md-block">
|
||||||
|
<label translate>extension.opc-device-name-pattern</label>
|
||||||
|
<input required
|
||||||
|
name="deviceNamePattern_{{serverIndex}}{{mapIndex}}"
|
||||||
|
ng-model="map.deviceNamePattern"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['deviceNamePattern_' + serverIndex + mapIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<v-accordion id="opc-attributes-accordion"
|
||||||
|
class="vAccordion--default"
|
||||||
|
>
|
||||||
|
<v-pane id="opc-attributes-pane">
|
||||||
|
<v-pane-header>
|
||||||
|
{{ 'extension.opc-mapping-attributes' | translate }}
|
||||||
|
</v-pane-header>
|
||||||
|
<v-pane-content>
|
||||||
|
<div ng-show="map.attributes.length > 0">
|
||||||
|
<ol class="list-group">
|
||||||
|
<li class="list-group-item"
|
||||||
|
ng-repeat="(attributeIndex, attribute) in map.attributes"
|
||||||
|
>
|
||||||
|
<md-button aria-label="{{ 'action.remove' | translate }}"
|
||||||
|
class="md-icon-button"
|
||||||
|
ng-click="removeItem(attribute, map.attributes)">
|
||||||
|
<ng-md-icon icon="close"
|
||||||
|
aria-label="{{ 'action.remove' | translate }}"
|
||||||
|
></ng-md-icon>
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'action.remove' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
</md-button>
|
||||||
|
<md-card>
|
||||||
|
<md-card-content>
|
||||||
|
|
||||||
|
<section flex
|
||||||
|
layout="row"
|
||||||
|
>
|
||||||
|
<md-input-container flex="60" class="md-block">
|
||||||
|
<label translate>extension.key</label>
|
||||||
|
<input required
|
||||||
|
name="opcAttributeKey_{{serverIndex}}{{mapIndex}}{{attributeIndex}}"
|
||||||
|
ng-model="attribute.key"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['opcAttributeKey_' + serverIndex + mapIndex + attributeIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
<md-input-container flex="40" class="md-block tb-container-for-select">
|
||||||
|
<label translate>extension.type</label>
|
||||||
|
<md-select required name="opcAttributeType_{{serverIndex}}{{mapIndex}}{{attributeIndex}}"
|
||||||
|
ng-model="attribute.type"
|
||||||
|
>
|
||||||
|
<md-option ng-repeat="(attrType, attrTypeValue) in types.extensionValueType"
|
||||||
|
ng-value="attrType"
|
||||||
|
>
|
||||||
|
{{attrTypeValue | translate}}
|
||||||
|
</md-option>
|
||||||
|
</md-select>
|
||||||
|
<div ng-messages="theForm['opcAttributeType_' + serverIndex + mapIndex + attributeIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.required-type</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section flex layout="row">
|
||||||
|
<md-input-container flex="100" class="md-block">
|
||||||
|
<label translate>extension.value</label>
|
||||||
|
<input required name="opcAttributeValue_{{serverIndex}}{{mapIndex}}{{attributeIndex}}"
|
||||||
|
ng-model="attribute.value"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['opcAttributeValue_' + serverIndex + mapIndex + attributeIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
|
</md-card-content>
|
||||||
|
</md-card>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div flex layout="row" layout-align="start center">
|
||||||
|
<md-button class="md-primary md-raised"
|
||||||
|
ng-click="addNewAttribute(map.attributes)"
|
||||||
|
aria-label="{{ 'action.add' | translate }}"
|
||||||
|
>
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'extension.add-map' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
<md-icon class="material-icons">add</md-icon>
|
||||||
|
<span translate>action.add</span>
|
||||||
|
</md-button>
|
||||||
|
</div>
|
||||||
|
</v-pane-content>
|
||||||
|
</v-pane>
|
||||||
|
</v-accordion>
|
||||||
|
|
||||||
|
<v-accordion id="opc-timeseries-accordion" class="vAccordion--default">
|
||||||
|
<v-pane id="opc-timeseries-pane">
|
||||||
|
<v-pane-header>
|
||||||
|
{{ 'extension.opc-timeseries' | translate }}
|
||||||
|
</v-pane-header>
|
||||||
|
<v-pane-content>
|
||||||
|
<div ng-show="map.timeseries.length > 0">
|
||||||
|
<ol class="list-group">
|
||||||
|
<li class="list-group-item"
|
||||||
|
ng-repeat="(timeseriesIndex, timeseries) in map.timeseries"
|
||||||
|
>
|
||||||
|
<md-button aria-label="{{ 'action.remove' | translate }}"
|
||||||
|
class="md-icon-button"
|
||||||
|
ng-click="removeItem(timeseries, map.timeseries)"
|
||||||
|
>
|
||||||
|
<ng-md-icon icon="close" aria-label="{{ 'action.remove' | translate }}"></ng-md-icon>
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'action.remove' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
</md-button>
|
||||||
|
<md-card>
|
||||||
|
<md-card-content>
|
||||||
|
<section flex layout="row">
|
||||||
|
<md-input-container flex="60" class="md-block">
|
||||||
|
<label translate>extension.key</label>
|
||||||
|
<input required
|
||||||
|
name="opcTimeseriesKey_{{serverIndex}}{{mapIndex}}{{timeseriesIndex}}"
|
||||||
|
ng-model="timeseries.key"
|
||||||
|
>
|
||||||
|
<div ng-messages="theForm['opcTimeseriesKey_' + serverIndex + mapIndex + timeseriesIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
<md-input-container flex="40"
|
||||||
|
class="md-block tb-container-for-select"
|
||||||
|
>
|
||||||
|
<label translate>extension.type</label>
|
||||||
|
<md-select required
|
||||||
|
name="opcTimeseriesType_{{serverIndex}}{{mapIndex}}{{timeseriesIndex}}"
|
||||||
|
ng-model="timeseries.type"
|
||||||
|
>
|
||||||
|
<md-option ng-repeat="(attrType, attrTypeValue) in types.extensionValueType"
|
||||||
|
ng-value="attrType"
|
||||||
|
>
|
||||||
|
{{attrTypeValue | translate}}
|
||||||
|
</md-option>
|
||||||
|
</md-select>
|
||||||
|
<div ng-messages="theForm['opcTimeseriesType_' + serverIndex + mapIndex + timeseriesIndex].$error">
|
||||||
|
<div translate
|
||||||
|
ng-message="required"
|
||||||
|
>extension.opc-field-required</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</section>
|
||||||
|
<section flex layout="row">
|
||||||
|
<md-input-container flex="100" class="md-block">
|
||||||
|
<label translate>extension.value</label>
|
||||||
|
<input required name="opcTimeseriesValue_{{serverIndex}}{{mapIndex}}{{timeseriesIndex}}" ng-model="timeseries.value">
|
||||||
|
<div ng-messages="theForm['opcTimeseriesValue_' + serverIndex + mapIndex + timeseriesIndex].$error">
|
||||||
|
<div translate ng-message="required">extension.required-value</div>
|
||||||
|
</div>
|
||||||
|
</md-input-container>
|
||||||
|
</section>
|
||||||
|
</md-card-content>
|
||||||
|
</md-card>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div flex layout="row" layout-align="start center">
|
||||||
|
<md-button class="md-primary md-raised"
|
||||||
|
ng-click="addNewAttribute(map.timeseries)"
|
||||||
|
aria-label="{{ 'action.add' | translate }}"
|
||||||
|
>
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'extension.add-timeseries' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
<md-icon class="material-icons">add</md-icon>
|
||||||
|
<span translate>action.add</span>
|
||||||
|
</md-button>
|
||||||
|
</div>
|
||||||
|
</v-pane-content>
|
||||||
|
</v-pane>
|
||||||
|
</v-accordion>
|
||||||
|
|
||||||
|
|
||||||
|
</md-card-content>
|
||||||
|
</md-card>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
<div flex
|
||||||
|
layout="row"
|
||||||
|
layout-align="start center"
|
||||||
|
>
|
||||||
|
<md-button class="md-primary md-raised"
|
||||||
|
ng-click="addMap(server.mapping)"
|
||||||
|
aria-label="{{ 'action.add' | translate }}"
|
||||||
|
>
|
||||||
|
<md-tooltip md-direction="top">
|
||||||
|
{{ 'extension.add-map' | translate }}
|
||||||
|
</md-tooltip>
|
||||||
|
<md-icon class="material-icons">add</md-icon>
|
||||||
|
<span translate>action.add</span>
|
||||||
|
</md-button>
|
||||||
|
</div>
|
||||||
|
</v-pane-content>
|
||||||
|
</v-pane>
|
||||||
|
</v-accordion>
|
||||||
|
|
||||||
|
</md-card-content>
|
||||||
|
</md-card>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div flex
|
||||||
|
layout="row"
|
||||||
|
layout-align="start center"
|
||||||
|
>
|
||||||
|
<md-button class="md-primary md-raised"
|
||||||
|
ng-click="addServer(configuration.servers)"
|
||||||
|
aria-label="{{ 'action.add' | translate }}"
|
||||||
|
>
|
||||||
|
<md-icon class="material-icons">add</md-icon>
|
||||||
|
<span translate>extension.opc-add-another-server</span>
|
||||||
|
</md-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</v-pane-content>
|
||||||
|
</v-pane>
|
||||||
|
</v-accordion>
|
||||||
|
<!--{{config}}-->
|
||||||
|
</md-card-content>
|
||||||
|
</md-card>
|
||||||
@ -38,3 +38,19 @@
|
|||||||
position:absolute!important
|
position:absolute!important
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.extensionDialog {
|
||||||
|
min-width: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-container-for-select {
|
||||||
|
height: 58px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tb-drop-file-input-hide {
|
||||||
|
height: 200%;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
import ExtensionTableDirective from './extension-table.directive';
|
import ExtensionTableDirective from './extension-table.directive';
|
||||||
import ExtensionFormHttpDirective from './extensions-forms/extension-form-http.directive';
|
import ExtensionFormHttpDirective from './extensions-forms/extension-form-http.directive';
|
||||||
|
import ExtensionFormOpcDirective from './extensions-forms/extension-form-opc.directive';
|
||||||
import {ParseToNull} from './extension-dialog.controller';
|
import {ParseToNull} from './extension-dialog.controller';
|
||||||
|
|
||||||
export default angular.module('thingsboard.extension', [])
|
export default angular.module('thingsboard.extension', [])
|
||||||
.directive('tbExtensionTable', ExtensionTableDirective)
|
.directive('tbExtensionTable', ExtensionTableDirective)
|
||||||
.directive('tbExtensionFormHttp', ExtensionFormHttpDirective)
|
.directive('tbExtensionFormHttp', ExtensionFormHttpDirective)
|
||||||
|
.directive('tbExtensionFormOpc', ExtensionFormOpcDirective)
|
||||||
.directive('parseToNull', ParseToNull)
|
.directive('parseToNull', ParseToNull)
|
||||||
.name;
|
.name;
|
||||||
@ -773,14 +773,44 @@ export default angular.module('thingsboard.locale', [])
|
|||||||
"json-parse": "Unable to parse transformer json.",
|
"json-parse": "Unable to parse transformer json.",
|
||||||
"attributes": "Attributes",
|
"attributes": "Attributes",
|
||||||
"add-attribute": "Add attribute",
|
"add-attribute": "Add attribute",
|
||||||
|
"add-map": "Add mapping element",
|
||||||
"timeseries": "Timeseries",
|
"timeseries": "Timeseries",
|
||||||
"add-timeseries": "Add timeseries",
|
"add-timeseries": "Add timeseries",
|
||||||
|
|
||||||
|
"opc-field-required": "Field is required",
|
||||||
|
"opc-server": "Servers",
|
||||||
|
"opc-add-server-hint": "Add server",
|
||||||
|
"opc-add-server-prompt": "Please add server",
|
||||||
|
"opc-server-id": "Server id",
|
||||||
|
"opc-timeseries": "Timeseries",
|
||||||
|
"opc-application-name": "Application name",
|
||||||
|
"opc-application-uri": "Application uri",
|
||||||
|
"opc-host": "Host",
|
||||||
|
"opc-port": "Port",
|
||||||
|
"opc-scan-period-in-seconds": "Scan period in seconds",
|
||||||
|
"opc-timeout-in-millis": "Timeout in milliseconds",
|
||||||
|
"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-mapping":"Mapping",
|
||||||
|
"opc-device-node-pattern":"Device node pattern",
|
||||||
|
"opc-device-name-pattern":"Device name pattern",
|
||||||
|
"opc-mapping-attributes":"Mapping attributes",
|
||||||
|
"opc-username":"Username",
|
||||||
|
"opc-password":"Password",
|
||||||
|
"opc-add-another-server":"Add another server",
|
||||||
},
|
},
|
||||||
"fullscreen": {
|
"fullscreen": {
|
||||||
"expand": "Expand to fullscreen",
|
"expand": "Expand to fullscreen",
|
||||||
"exit": "Exit fullscreen",
|
"exit": "Exit fullscreen",
|
||||||
"toggle": "Toggle fullscreen mode",
|
"toggle": "Toggle fullscreen mode",
|
||||||
"fullscreen": "Fullscreen"
|
"fullscreen": "Fullscreen",
|
||||||
},
|
},
|
||||||
"function": {
|
"function": {
|
||||||
"function": "Function"
|
"function": "Function"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user