Browse Source
* Change translate, layout and clear code * Refactoring code * Refactoring code * Refactoring code * Code refactoringpull/2397/head
committed by
GitHub
18 changed files with 1078 additions and 1248 deletions
@ -1,317 +0,0 @@ |
|||||
/* |
|
||||
* Copyright © 2016-2020 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 './gateway-config.scss'; |
|
||||
|
|
||||
/* eslint-disable import/no-unresolved, import/default */ |
|
||||
|
|
||||
import gatewayTemplate from './gateway-config.tpl.html'; |
|
||||
import gatewayDialogTemplate from './gateway-config-dialog.tpl.html'; |
|
||||
import beautify from "js-beautify"; |
|
||||
|
|
||||
/* eslint-enable import/no-unresolved, import/default */ |
|
||||
const js_beautify = beautify.js; |
|
||||
|
|
||||
export default angular.module('thingsboard.directives.gatewayConfig', []) |
|
||||
.directive('tbGatewayConfig', GatewayConfig) |
|
||||
.name; |
|
||||
|
|
||||
/*@ngInject*/ |
|
||||
function GatewayConfig() { |
|
||||
return { |
|
||||
restrict: "E", |
|
||||
scope: true, |
|
||||
bindToController: { |
|
||||
disabled: '=ngDisabled', |
|
||||
titleText: '@?', |
|
||||
keyPlaceholderText: '@?', |
|
||||
valuePlaceholderText: '@?', |
|
||||
noDataText: '@?', |
|
||||
gatewayConfig: '=', |
|
||||
changeAlignment: '=' |
|
||||
}, |
|
||||
controller: GatewayConfigController, |
|
||||
controllerAs: 'vm', |
|
||||
templateUrl: gatewayTemplate |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
/*@ngInject*/ |
|
||||
function GatewayConfigController($scope, $document, $mdDialog, $mdUtil, $window, types, toast, $timeout, $compile, $translate) { //eslint-disable-line
|
|
||||
|
|
||||
let vm = this; |
|
||||
|
|
||||
vm.kvList = []; |
|
||||
vm.types = types; |
|
||||
$scope.$watch('vm.gatewayConfig', () => { |
|
||||
vm.stopWatchKvList(); |
|
||||
vm.kvList.length = 0; |
|
||||
if (vm.gatewayConfig) { |
|
||||
for (var property in vm.gatewayConfig) { |
|
||||
if (Object.prototype.hasOwnProperty.call(vm.gatewayConfig, property)) { |
|
||||
vm.kvList.push( |
|
||||
{ |
|
||||
enabled: vm.gatewayConfig[property].enabled, |
|
||||
key: property + '', |
|
||||
value: vm.gatewayConfig[property].connector + '', |
|
||||
config: js_beautify(vm.gatewayConfig[property].config + '', {indent_size: 4}) |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
$mdUtil.nextTick(() => { |
|
||||
vm.watchKvList(); |
|
||||
}); |
|
||||
}); |
|
||||
|
|
||||
vm.watchKvList = () => { |
|
||||
$scope.kvListWatcher = $scope.$watch('vm.kvList', () => { |
|
||||
if (!vm.gatewayConfig) { |
|
||||
return; |
|
||||
} |
|
||||
for (let property in vm.gatewayConfig) { |
|
||||
if (Object.prototype.hasOwnProperty.call(vm.gatewayConfig, property)) { |
|
||||
delete vm.gatewayConfig[property]; |
|
||||
} |
|
||||
} |
|
||||
for (let i = 0; i < vm.kvList.length; i++) { |
|
||||
let entry = vm.kvList[i]; |
|
||||
if (entry.key && entry.value) { |
|
||||
let connectorJSON = angular.toJson({ |
|
||||
enabled: entry.enabled, |
|
||||
connector: entry.value, |
|
||||
config: angular.fromJson(entry.config) |
|
||||
}); |
|
||||
vm.gatewayConfig [entry.key] = angular.fromJson(connectorJSON); |
|
||||
} |
|
||||
} |
|
||||
}, true); |
|
||||
}; |
|
||||
|
|
||||
vm.stopWatchKvList = () => { |
|
||||
if ($scope.kvListWatcher) { |
|
||||
$scope.kvListWatcher(); |
|
||||
$scope.kvListWatcher = null; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.removeKeyVal = (index) => { |
|
||||
if (index > -1) { |
|
||||
vm.kvList.splice(index, 1); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.addKeyVal = () => { |
|
||||
if (!vm.kvList) { |
|
||||
vm.kvList = []; |
|
||||
} |
|
||||
vm.kvList.push( |
|
||||
{ |
|
||||
enabled: false, |
|
||||
key: '', |
|
||||
value: '', |
|
||||
config: '{}' |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
vm.openConfigDialog = ($event, index, config, typeName) => { |
|
||||
if ($event) { |
|
||||
$event.stopPropagation(); |
|
||||
} |
|
||||
$mdDialog.show({ |
|
||||
controller: GatewayDialogController, |
|
||||
controllerAs: 'vm', |
|
||||
templateUrl: gatewayDialogTemplate, |
|
||||
parent: angular.element($document[0].body), |
|
||||
locals: { |
|
||||
config: config, |
|
||||
typeName: typeName |
|
||||
}, |
|
||||
targetEvent: $event, |
|
||||
fullscreen: true, |
|
||||
multiple: true, |
|
||||
}).then(function (config) { |
|
||||
if (config) { |
|
||||
if (index > -1) { |
|
||||
vm.kvList[index].config = config; |
|
||||
} |
|
||||
} |
|
||||
}, function () { |
|
||||
}); |
|
||||
|
|
||||
}; |
|
||||
|
|
||||
vm.configTypeChange = (keyVal) => { |
|
||||
for (let prop in types.gatewayConfigType) { |
|
||||
if (types.gatewayConfigType[prop].value === keyVal.value) { |
|
||||
if (!keyVal.key) { |
|
||||
keyVal.key = vm.configTypeChangeValid(types.gatewayConfigType[prop].name, 0); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
vm.checkboxValid(keyVal); |
|
||||
}; |
|
||||
|
|
||||
vm.keyValChange = (keyVal, indexKey) => { |
|
||||
keyVal.key = vm.keyValChangeValid(keyVal.key, 0, indexKey); |
|
||||
vm.checkboxValid(keyVal); |
|
||||
}; |
|
||||
|
|
||||
vm.configTypeChangeValid = (name, index) => { |
|
||||
let newKeyName = index ? name + index : name; |
|
||||
let indexRes = vm.kvList.findIndex((element) => element.key === newKeyName); |
|
||||
return indexRes === -1 ? newKeyName : vm.configTypeChangeValid(name, ++index); |
|
||||
}; |
|
||||
|
|
||||
vm.keyValChangeValid = (name, index, indexKey) => { |
|
||||
angular.forEach(vm.kvList, function (value, key) { |
|
||||
let nameEq = (index === 0) ? name : name + index; |
|
||||
if (key !== indexKey && value.key && value.key === nameEq) { |
|
||||
index++; |
|
||||
vm.keyValChangeValid(name, index, indexKey); |
|
||||
} |
|
||||
|
|
||||
}); |
|
||||
return (index === 0) ? name : name + index; |
|
||||
}; |
|
||||
|
|
||||
vm.buttonValid = (config) => { |
|
||||
return (angular.equals("{}", config)) ? "md-warn" : "md-primary"; |
|
||||
}; |
|
||||
|
|
||||
vm.checkboxValid = (keyVal) => { |
|
||||
if (!keyVal.key || angular.equals("", keyVal.key) |
|
||||
|| !keyVal.value || angular.equals("", keyVal.value) |
|
||||
|| angular.equals("{}", keyVal.config)) { |
|
||||
return keyVal.enabled = false; |
|
||||
} |
|
||||
return true; |
|
||||
}; |
|
||||
vm.checkboxValidMouseover = ($event, keyVal) => { |
|
||||
console.log($event, keyVal); //eslint-disable-line
|
|
||||
vm.checkboxValidClick ($event, keyVal); |
|
||||
}; |
|
||||
|
|
||||
vm.checkboxValidClick = ($event, keyVal) => { |
|
||||
if (!vm.checkboxValid(keyVal)) { |
|
||||
let errTxt = ""; |
|
||||
if (!keyVal.key || angular.equals("", keyVal.key)) { |
|
||||
errTxt = $translate.instant('gateway.keyval-name-err'); |
|
||||
} |
|
||||
|
|
||||
if (!keyVal.value || angular.equals("", keyVal.value)) { |
|
||||
errTxt += '<div>' + $translate.instant('gateway.keyval-type-err') + '</div>'; |
|
||||
} |
|
||||
|
|
||||
if (angular.equals("{}", keyVal.config)) { |
|
||||
errTxt += '<div>' + $translate.instant('gateway.keyval-config-err') + '</div>'; |
|
||||
} |
|
||||
if (!angular.equals("", errTxt)) { |
|
||||
displayTooltip($event, '<div class="tb-rule-node-tooltip tb-lib-tooltip">' + |
|
||||
'<div id="tb-node-content" layout="column">' + |
|
||||
'<div class="tb-node-title">' + $translate.instant('gateway.keyval-save-err') + '</div>' + |
|
||||
'<div class="tb-node-details">' + errTxt + '</div>' + |
|
||||
'</div>' + |
|
||||
'</div>'); |
|
||||
} |
|
||||
} |
|
||||
else { |
|
||||
destroyTooltips(); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
function displayTooltip(event, content) { |
|
||||
destroyTooltips(); |
|
||||
vm.tooltipTimeout = $timeout(() => { |
|
||||
var element = angular.element(event.target); |
|
||||
element.tooltipster( |
|
||||
{ |
|
||||
theme: 'tooltipster-shadow', |
|
||||
delay: 10, |
|
||||
animation: 'grow', |
|
||||
side: 'right' |
|
||||
} |
|
||||
); |
|
||||
var contentElement = angular.element(content); |
|
||||
$compile(contentElement)($scope); |
|
||||
var tooltip = element.tooltipster('instance'); |
|
||||
tooltip.content(contentElement); |
|
||||
tooltip.open(); |
|
||||
}, 500); |
|
||||
} |
|
||||
|
|
||||
function destroyTooltips() { |
|
||||
if (vm.tooltipTimeout) { |
|
||||
$timeout.cancel(vm.tooltipTimeout); |
|
||||
vm.tooltipTimeout = null; |
|
||||
} |
|
||||
var instances = angular.element.tooltipster.instances(); |
|
||||
instances.forEach((instance) => { |
|
||||
if (!instance.isErrorTooltip) { |
|
||||
instance.destroy(); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/*@ngInject*/ |
|
||||
function GatewayDialogController($scope, $mdDialog, $document, $window, config, typeName) { |
|
||||
let vm = this; |
|
||||
vm.doc = $document[0]; |
|
||||
vm.config = angular.copy(config); |
|
||||
vm.typeName = "" + typeName; |
|
||||
vm.configAreaOptions = { |
|
||||
useWrapMode: false, |
|
||||
mode: 'json', |
|
||||
showGutter: true, |
|
||||
showPrintMargin: true, |
|
||||
theme: 'github', |
|
||||
advanced: { |
|
||||
enableSnippets: true, |
|
||||
enableBasicAutocompletion: true, |
|
||||
enableLiveAutocompletion: true |
|
||||
}, |
|
||||
onLoad: function (_ace) { |
|
||||
_ace.$blockScrolling = 1; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.validateConfig = (model, editorName) => { |
|
||||
if (model && model.length) { |
|
||||
try { |
|
||||
angular.fromJson(model); |
|
||||
$scope.theForm[editorName].$setValidity('configJSON', true); |
|
||||
} catch (e) { |
|
||||
$scope.theForm[editorName].$setValidity('configJSON', false); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.save = () => { |
|
||||
$mdDialog.hide(vm.config); |
|
||||
}; |
|
||||
|
|
||||
vm.cancel = () => { |
|
||||
$mdDialog.hide(); |
|
||||
}; |
|
||||
|
|
||||
vm.beautifyJson = () => { |
|
||||
vm.config = js_beautify(vm.config, {indent_size: 4}); |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
@ -1,94 +0,0 @@ |
|||||
<!-- |
|
||||
|
|
||||
Copyright © 2016-2020 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. |
|
||||
|
|
||||
--> |
|
||||
<form name="gatewayConfig" flex layout="column" class="gateway-config"> |
|
||||
<div layout="row" id="section-row" ng-repeat="keyVal in vm.kvList track by $index"> |
|
||||
<div layout="column" layout-align="center center" class="gateway-config-row"> |
|
||||
<md-input-container class="md-block"> |
|
||||
<md-checkbox ng-model="keyVal.enabled" |
|
||||
aria-label="{{ 'gateway.enabled' | translate }}" |
|
||||
ng-change="vm.checkboxValid(keyVal)" |
|
||||
ng-click="vm.checkboxValidClick($event, keyVal)" |
|
||||
ng-mouseover="vm.checkboxValidMouseover($event, keyVal)"> |
|
||||
</md-checkbox> |
|
||||
<md-tooltip md-direction="top"> |
|
||||
{{ 'gateway.enabled' | translate }} |
|
||||
</md-tooltip> |
|
||||
</md-input-container> |
|
||||
</div> |
|
||||
<div layout="row" flex class="gateway-config-row" |
|
||||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{'gateway.connector-type' | translate }}</label> |
|
||||
<md-select name="configType" ng-change="vm.configTypeChange(keyVal)" ng-model="keyVal.value" required> |
|
||||
<md-option ng-repeat="configType in vm.types.gatewayConfigType" ng-value="configType.value"> |
|
||||
{{configType.value}} |
|
||||
</md-option> |
|
||||
</md-select> |
|
||||
<md-tooltip md-direction="top"> |
|
||||
{{ 'gateway.connector-type' | translate }} |
|
||||
</md-tooltip> |
|
||||
</md-input-container> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<input placeholder="{{ (vm.keyPlaceholderText ? vm.keyPlaceholderText : 'gateway.name') | translate }}" |
|
||||
ng-model-options="{ updateOn: 'blur' }" |
|
||||
ng-change="vm.keyValChange(keyVal, $index)" name="key" ng-model="keyVal.key" required/> |
|
||||
<div ng-messages="gatewayConfig.key.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
</div> |
|
||||
<md-tooltip md-direction="top"> |
|
||||
{{ 'gateway.name' | translate }} |
|
||||
</md-tooltip> |
|
||||
</md-input-container> |
|
||||
</div> |
|
||||
<div layout="row" layout-align="end center" class="action-buttons" |
|
||||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|
||||
<md-button class="md-icon-button md-fab md-mini" |
|
||||
name="updateconf" |
|
||||
ng-click="vm.openConfigDialog($event, $index, keyVal.config, keyVal.key)" |
|
||||
aria-label="{{ 'gateway.update-config' | translate }}" |
|
||||
ng-class="vm.buttonValid(keyVal.config)" required> |
|
||||
<md-icon class="material-icons">settings_ethernet</md-icon> |
|
||||
<md-tooltip md-direction="top"> |
|
||||
{{ 'gateway.update-config' | translate }} |
|
||||
</md-tooltip> |
|
||||
</md-button> |
|
||||
<md-button ng-show="!vm.disabled" ng-disabled="$root.loading" |
|
||||
class="md-icon-button md-fab md-mini md-primary" |
|
||||
ng-click="vm.removeKeyVal($index)" |
|
||||
aria-label="{{ 'gateway.delete' | translate }}"> |
|
||||
<md-icon class="material-icons">close</md-icon> |
|
||||
<md-tooltip md-direction="top"> |
|
||||
{{ 'gateway.delete' | translate }} |
|
||||
</md-tooltip> |
|
||||
</md-button> |
|
||||
</div> |
|
||||
</div> |
|
||||
<span ng-show="!vm.kvList.length" |
|
||||
layout-align="center center" ng-class="{'disabled': vm.disabled}" |
|
||||
class="no-data-found" translate>{{vm.noDataText ? vm.noDataText : 'gateway.no-connectors'}}</span> |
|
||||
<div> |
|
||||
<md-button ng-show="!vm.disabled" ng-disabled="$root.loading" class="md-raised" |
|
||||
ng-click="vm.addKeyVal()" |
|
||||
aria-label="{{ 'gateway.add-connectors' | translate }}"> |
|
||||
<md-tooltip md-direction="top"> |
|
||||
{{ 'gateway.add-connectors' | translate }} |
|
||||
</md-tooltip> |
|
||||
<span translate>action.add</span> |
|
||||
</md-button> |
|
||||
</div> |
|
||||
</form > |
|
||||
@ -1,498 +0,0 @@ |
|||||
/* |
|
||||
* Copyright © 2016-2020 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 './gateway-form.scss'; |
|
||||
/* eslint-disable import/no-unresolved, import/default */ |
|
||||
|
|
||||
import gatewayFormTemplate from './gateway-form.tpl.html'; |
|
||||
|
|
||||
/* eslint-enable import/no-unresolved, import/default */ |
|
||||
|
|
||||
export default angular.module('thingsboard.directives.gatewayForm', []) |
|
||||
.directive('tbGatewayForm', GatewayForm) |
|
||||
.name; |
|
||||
|
|
||||
/*@ngInject*/ |
|
||||
function GatewayForm() { |
|
||||
return { |
|
||||
restrict: "E", |
|
||||
scope: true, |
|
||||
bindToController: { |
|
||||
disabled: '=ngDisabled', |
|
||||
keyPlaceholderText: '@?', |
|
||||
valuePlaceholderText: '@?', |
|
||||
noDataText: '@?', |
|
||||
formId: '=', |
|
||||
ctx: '=', |
|
||||
gatewayFormConfig: '=', |
|
||||
theForm: '=' |
|
||||
}, |
|
||||
controller: GatewayFormController, |
|
||||
controllerAs: 'vm', |
|
||||
templateUrl: gatewayFormTemplate |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
/*@ngInject*/ |
|
||||
function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, toast, importExport, attributeService, deviceService, userService, $mdDialog, $mdUtil, types, $window, $q) { |
|
||||
$scope.$mdExpansionPanel = $mdExpansionPanel; |
|
||||
let vm = this; |
|
||||
const attributeNameClinet = "current_configuration"; |
|
||||
const attributeNameServer = "configuration_drafts"; |
|
||||
const attributeNameShared = "configuration"; |
|
||||
const attributeNameLogShared = "RemoteLoggingLevel"; |
|
||||
vm.remoteLoggingConfig = '[loggers]}}keys=root, service, connector, converter, tb_connection, storage, extension}}[handlers]}}keys=consoleHandler, serviceHandler, connectorHandler, converterHandler, tb_connectionHandler, storageHandler, extensionHandler}}[formatters]}}keys=LogFormatter}}[logger_root]}}level=ERROR}}handlers=consoleHandler}}[logger_connector]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=connector}}[logger_storage]}}level={ERROR}}}handlers=storageHandler}}formatter=LogFormatter}}qualname=storage}}[logger_tb_connection]}}level={ERROR}}}handlers=tb_connectionHandler}}formatter=LogFormatter}}qualname=tb_connection}}[logger_service]}}level={ERROR}}}handlers=serviceHandler}}formatter=LogFormatter}}qualname=service}}[logger_converter]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=converter}}[logger_extension]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=extension}}[handler_consoleHandler]}}class=StreamHandler}}level={ERROR}}}formatter=LogFormatter}}args=(sys.stdout,)}}[handler_connectorHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}connector.log", "d", 1, 7,)}}[handler_storageHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}storage.log", "d", 1, 7,)}}[handler_serviceHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}service.log", "d", 1, 7,)}}[handler_converterHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}converter.log", "d", 1, 3,)}}[handler_extensionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}extension.log", "d", 1, 3,)}}[handler_tb_connectionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}tb_connection.log", "d", 1, 3,)}}[formatter_LogFormatter]}}format="%(asctime)s - %(levelname)s - [%(filename)s] - %(module)s - %(lineno)d - %(message)s" }}datefmt="%Y-%m-%d %H:%M:%S"'; |
|
||||
vm.types = types; |
|
||||
|
|
||||
vm.configurations = { |
|
||||
singleSelect: '', |
|
||||
host: $document[0].domain, |
|
||||
port: 1883, |
|
||||
remoteConfiguration: true, |
|
||||
accessToken: '', |
|
||||
entityType: '', |
|
||||
entityId: '', |
|
||||
storageType: "memoryStorage", // "memoryStorage"; fileStorage
|
|
||||
readRecordsCount: 100, |
|
||||
maxRecordsCount: 10000, |
|
||||
dataFolderPath: './data/', |
|
||||
maxFilesCount: 5, |
|
||||
securityType: "accessToken", // "accessToken", "tls"
|
|
||||
caCertPath: '/etc/thingsboard-gateway/ca.pem', |
|
||||
privateKeyPath: '/etc/thingsboard-gateway/privateKey.pem', |
|
||||
certPath: '/etc/thingsboard-gateway/certificate.pem', |
|
||||
connectors: {}, |
|
||||
remoteLoggingLevel: "DEBUG", // level login
|
|
||||
remoteLoggingPathToLogs: './logs/' |
|
||||
}; |
|
||||
getGatewaysListByUser(true); |
|
||||
|
|
||||
vm.securityTypes = [{ |
|
||||
name: 'Access Token', |
|
||||
value: 'accessToken' |
|
||||
}, { |
|
||||
name: 'TLS', |
|
||||
value: 'tls' |
|
||||
}]; |
|
||||
|
|
||||
vm.storageTypes = [{ |
|
||||
name: 'Memory storage', |
|
||||
value: 'memoryStorage' |
|
||||
}, { |
|
||||
name: 'File storage', |
|
||||
value: 'fileStorage' |
|
||||
}]; |
|
||||
|
|
||||
$scope.$on('gateway-form-resize', function (event, formId) { |
|
||||
if (vm.formId == formId) { |
|
||||
updateWidgetDisplaying(); |
|
||||
} |
|
||||
}); |
|
||||
|
|
||||
function updateWidgetDisplaying() { |
|
||||
if (vm.ctx && vm.ctx.$container) { |
|
||||
vm.changeAlignment = (vm.ctx.$container[0].offsetWidth <= 425); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
updateWidgetDisplaying(); |
|
||||
|
|
||||
vm.getAccessToken = (deviceObj) => { |
|
||||
if (deviceObj.name) { |
|
||||
deviceService.findByName(deviceObj.name, {ignoreErrors: true}) |
|
||||
.then( |
|
||||
function (device) { |
|
||||
getDeviceCredential(device.id.id); |
|
||||
} |
|
||||
) |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
function getDeviceCredential(deviceId) { |
|
||||
return deviceService.getDeviceCredentials(deviceId).then( |
|
||||
(deviceCredentials) => { |
|
||||
vm.configurations.accessToken = deviceCredentials.credentialsId; |
|
||||
vm.configurations.entityType = deviceCredentials.deviceId.entityType; |
|
||||
vm.configurations.entityId = deviceCredentials.deviceId.id; |
|
||||
vm.getAttributeStart(); |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
vm.createDevice = (deviceObj) => { |
|
||||
deviceService.findByName(deviceObj.name, {ignoreErrors: true}) |
|
||||
.then( |
|
||||
function (device) { |
|
||||
getDeviceCredential(device.id.id).then(() => { |
|
||||
getGatewaysListByUser(); |
|
||||
}); |
|
||||
}, |
|
||||
function () { |
|
||||
deviceService.saveDevice(deviceObj).then( |
|
||||
(device) => { |
|
||||
deviceService.getDeviceCredentials(device.id.id).then( |
|
||||
(data) => { |
|
||||
vm.configurations.accessToken = data.credentialsId; |
|
||||
vm.configurations.entityType = device.id.entityType; |
|
||||
vm.configurations.entityId = device.id.id; |
|
||||
vm.getAttributeStart(); |
|
||||
getGatewaysListByUser(); |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
); |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
vm.saveAttributeConfig = () => { |
|
||||
vm.setAttribute(attributeNameShared, $window.btoa(angular.toJson(vm.getConfigAllByAttributeJSON())), types.attributesScope.shared.value); |
|
||||
vm.setAttribute(attributeNameServer, $window.btoa(angular.toJson(vm.getConfigByAttributeTmpJSON())), types.attributesScope.server.value); |
|
||||
vm.setAttribute(attributeNameLogShared, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value); |
|
||||
}; |
|
||||
|
|
||||
vm.getAttributeStart = () => { |
|
||||
let initResps = []; |
|
||||
vm.configurations.connectors = {}; |
|
||||
initResps.push(vm.getAttributeConfig(attributeNameClinet, types.attributesScope.client.value)); |
|
||||
initResps.push(vm.getAttributeConfig(attributeNameServer, types.attributesScope.server.value)); |
|
||||
initResps.push(vm.getAttributeConfig(attributeNameLogShared, types.attributesScope.shared.value)); |
|
||||
$q.all(initResps).then((resp) => { |
|
||||
vm.getAttributeInitFromClient(resp[0]); |
|
||||
vm.getAttributeInitFromServer(resp[1]); |
|
||||
vm.getAttributeInitFromShared(resp[2]); |
|
||||
}, (err) => { |
|
||||
console.log("getAttribute_error", err); //eslint-disable-line
|
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
vm.getAttributeConfig = (attributeName, typeValue) => { |
|
||||
let keys = [attributeName]; |
|
||||
return attributeService.getEntityAttributesValues(vm.configurations.entityType, vm.configurations.entityId, typeValue, keys); |
|
||||
}; |
|
||||
|
|
||||
vm.setAttribute = (attributeName, attributeConfig, typeValue) => { |
|
||||
let attributes = [ |
|
||||
{ |
|
||||
key: attributeName, |
|
||||
value: attributeConfig |
|
||||
} |
|
||||
]; |
|
||||
attributeService.saveEntityAttributes(vm.configurations.entityType, vm.configurations.entityId, typeValue, attributes).then(() => { |
|
||||
}, (err) => { |
|
||||
console.log("setAttribute_", err); //eslint-disable-line
|
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
vm.exportConfig = () => { |
|
||||
let fileZip = {}; |
|
||||
fileZip["tb_gateway.yaml"] = vm.getConfig(); |
|
||||
vm.createConfigByExport(fileZip); |
|
||||
vm.getLogsConfigByExport(fileZip); |
|
||||
importExport.exportJSZip(fileZip, 'config'); |
|
||||
vm.setAttribute(attributeNameLogShared, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value); |
|
||||
}; |
|
||||
|
|
||||
vm.getConfig = () => { |
|
||||
let config; |
|
||||
config = 'thingsboard:\n'; |
|
||||
config += ' host: ' + vm.configurations.host + '\n'; |
|
||||
config += ' remoteConfiguration: ' + vm.configurations.remoteConfiguration + '\n'; |
|
||||
config += ' port: ' + vm.configurations.port + '\n'; |
|
||||
config += ' security:\n'; |
|
||||
if (vm.configurations.securityType === 'accessToken') { |
|
||||
config += ' access-token: ' + vm.configurations.accessToken + '\n'; |
|
||||
} else if (vm.configurations.securityType === 'tls') { |
|
||||
config += ' ca_cert: ' + vm.configurations.caCertPath + '\n'; |
|
||||
config += ' privateKey: ' + vm.configurations.privateKeyPath + '\n'; |
|
||||
config += ' cert: ' + vm.configurations.certPath + '\n'; |
|
||||
} |
|
||||
config += 'storage:\n'; |
|
||||
if (vm.configurations.storageType === 'memoryStorage') { |
|
||||
config += ' type: memory\n'; |
|
||||
config += ' read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
|
||||
config += ' max_records_count: ' + vm.configurations.maxRecordsCount + '\n'; |
|
||||
} else if (vm.configurations.storageType === 'fileStorage') { |
|
||||
config += ' type: file\n'; |
|
||||
config += ' data_folder_path: ' + vm.configurations.dataFolderPath + '\n'; |
|
||||
config += ' max_file_count: ' + vm.configurations.maxFilesCount + '\n'; |
|
||||
config += ' max_read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
|
||||
config += ' max_records_per_file: ' + vm.configurations.maxRecordsCount + '\n'; |
|
||||
} |
|
||||
config += 'connectors:\n'; |
|
||||
for (let connector in vm.configurations.connectors) { |
|
||||
if (vm.configurations.connectors[connector].enabled) { |
|
||||
config += ' -\n'; |
|
||||
config += ' name: ' + connector + ' Connector\n'; |
|
||||
config += ' type: ' + vm.configurations.connectors[connector].connector + '\n'; |
|
||||
config += ' configuration: ' + vm.validFileName(connector) + ".json" + '\n'; |
|
||||
} |
|
||||
} |
|
||||
return config; |
|
||||
}; |
|
||||
|
|
||||
vm.createConfigByExport = (fileZipAdd) => { |
|
||||
for (let connector in vm.configurations.connectors) { |
|
||||
if (vm.configurations.connectors[connector].enabled) { |
|
||||
fileZipAdd[vm.validFileName(connector) + ".json"] = angular.toJson(vm.configurations.connectors[connector].config); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.getLogsConfigByExport = (fileZipAdd) => { |
|
||||
fileZipAdd["logs.conf"] = vm.getLogsConfig(); |
|
||||
}; |
|
||||
|
|
||||
vm.getLogsConfig = () => { |
|
||||
return vm.remoteLoggingConfig |
|
||||
.replace(/{ERROR}/g, vm.configurations.remoteLoggingLevel) |
|
||||
.replace(/{.\/logs\/}/g, vm.configurations.remoteLoggingPathToLogs); |
|
||||
}; |
|
||||
|
|
||||
vm.getConfigAllByAttributeJSON = () => { |
|
||||
let thingsBoardAll = {}; |
|
||||
thingsBoardAll["thingsboard"] = vm.getConfigMainByAttributeJSON(); |
|
||||
vm.getConfigByAttributeJSON(thingsBoardAll); |
|
||||
return thingsBoardAll; |
|
||||
}; |
|
||||
|
|
||||
vm.getConfigMainByAttributeJSON = () => { |
|
||||
let configMain = {}; |
|
||||
let thingsBoard = {}; |
|
||||
thingsBoard.host = vm.configurations.host; |
|
||||
thingsBoard.remoteConfiguration = vm.configurations.remoteConfiguration; |
|
||||
thingsBoard.port = vm.configurations.port; |
|
||||
let security = {}; |
|
||||
if (vm.configurations.securityType === 'accessToken') { |
|
||||
security.accessToken = (vm.configurations.accessToken) ? vm.configurations.accessToken : "" |
|
||||
} else { |
|
||||
security.caCert = vm.configurations.caCertPath; |
|
||||
security.privateKey = vm.configurations.privateKeyPath; |
|
||||
security.cert = vm.configurations.certPath; |
|
||||
} |
|
||||
thingsBoard.security = security; |
|
||||
configMain.thingsboard = thingsBoard; |
|
||||
|
|
||||
let storage = {}; |
|
||||
if (vm.configurations.storageType === 'memoryStorage') { |
|
||||
storage.type = "memory"; |
|
||||
storage.read_records_count = vm.configurations.readRecordsCount; |
|
||||
storage.max_records_count = vm.configurations.maxRecordsCount; |
|
||||
} else if (vm.configurations.storageType === 'fileStorage') { |
|
||||
storage.type = "file"; |
|
||||
storage.data_folder_path = vm.configurations.dataFolderPath; |
|
||||
storage.max_file_count = vm.configurations.maxFilesCount; |
|
||||
storage.max_read_records_count = vm.configurations.readRecordsCount; |
|
||||
storage.max_records_per_file = vm.configurations.maxRecordsCount; |
|
||||
} |
|
||||
configMain.storage = storage; |
|
||||
|
|
||||
let conn = []; |
|
||||
for (let connector in vm.configurations.connectors) { |
|
||||
if (vm.configurations.connectors[connector].enabled) { |
|
||||
let connect = {}; |
|
||||
connect.configuration = vm.validFileName(connector) + ".json"; |
|
||||
connect.name = connector; |
|
||||
connect.type = vm.configurations.connectors[connector].connector; |
|
||||
conn.push(connect); |
|
||||
} |
|
||||
} |
|
||||
configMain.connectors = conn; |
|
||||
|
|
||||
configMain.logs = $window.btoa(vm.getLogsConfig()); |
|
||||
|
|
||||
return configMain; |
|
||||
}; |
|
||||
|
|
||||
vm.getConfigByAttributeJSON = (thingsBoardBy) => { |
|
||||
for (let connector in vm.configurations.connectors) { |
|
||||
if (vm.configurations.connectors[connector].enabled) { |
|
||||
let typeAr = vm.configurations.connectors[connector].connector; |
|
||||
let objTypeAll = []; |
|
||||
for (let conn in vm.configurations.connectors) { |
|
||||
if (typeAr === vm.configurations.connectors[conn].connector && vm.configurations.connectors[conn].enabled) { |
|
||||
let objType = {}; |
|
||||
objType["name"] = conn; |
|
||||
objType["config"] = vm.configurations.connectors[conn].config; |
|
||||
objTypeAll.push(objType); |
|
||||
} |
|
||||
} |
|
||||
if (objTypeAll.length > 0) { |
|
||||
thingsBoardBy[typeAr] = objTypeAll; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.getConfigByAttributeTmpJSON = () => { |
|
||||
let connects = {}; |
|
||||
for (let connector in vm.configurations.connectors) { |
|
||||
if (!vm.configurations.connectors[connector].enabled && Object.keys(vm.configurations.connectors[connector].config).length !== 0) { |
|
||||
let conn = {}; |
|
||||
conn["connector"] = vm.configurations.connectors[connector].connector; |
|
||||
conn["config"] = vm.configurations.connectors[connector].config; |
|
||||
connects[connector] = conn; |
|
||||
} |
|
||||
} |
|
||||
return connects; |
|
||||
}; |
|
||||
|
|
||||
function getGatewaysListByUser(firstInit) { |
|
||||
vm.gateways = []; |
|
||||
vm.currentUser = userService.getCurrentUser(); |
|
||||
if (vm.currentUser.authority === 'TENANT_ADMIN') { |
|
||||
deviceService.getTenantDevices({limit: 500}).then( |
|
||||
(devices) => { |
|
||||
if (devices.data.length > 0) { |
|
||||
devices.data.forEach((device) => { |
|
||||
if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { |
|
||||
vm.gateways.push(device.name); |
|
||||
if (firstInit && vm.gateways.length && device.name === vm.gateways[0]) { |
|
||||
vm.configurations.singleSelect = vm.gateways[0]; |
|
||||
let deviceObj = { |
|
||||
"name": vm.configurations.singleSelect, |
|
||||
"type": "Gateway", |
|
||||
"additionalInfo": { |
|
||||
"gateway": true |
|
||||
} |
|
||||
}; |
|
||||
vm.getAccessToken(deviceObj); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
); |
|
||||
} else if (vm.currentUser.authority === 'CUSTOMER_USER') { |
|
||||
deviceService.getCustomerDevices(vm.currentUser.customerId, {limit: 500}).then( |
|
||||
(devices) => { |
|
||||
if (devices.data.length > 0) { |
|
||||
devices.data.forEach((device) => { |
|
||||
if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { |
|
||||
vm.gateways.push(device.name); |
|
||||
if (firstInit && vm.gateways.length) { |
|
||||
vm.configurations.singleSelect = vm.gateways[0]; |
|
||||
let deviceObj = { |
|
||||
"name": vm.configurations.singleSelect, |
|
||||
"type": "Gateway", |
|
||||
"additionalInfo": { |
|
||||
"gateway": true |
|
||||
} |
|
||||
}; |
|
||||
vm.getAccessToken(deviceObj); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
vm.getAttributeInitFromClient = (resp) => { |
|
||||
if (resp.length > 0) { |
|
||||
vm.configurations.connectors = {}; |
|
||||
let attribute = angular.fromJson($window.atob(resp[0].value)); |
|
||||
for (var type in attribute) { |
|
||||
let keyVal = attribute[type]; |
|
||||
if (type === "thingsboard") { |
|
||||
if (keyVal !== null && Object.keys(keyVal).length > 0) { |
|
||||
vm.setConfigMain(keyVal); |
|
||||
} |
|
||||
} else { |
|
||||
for (let typeVal in keyVal) { |
|
||||
let typeName = ''; |
|
||||
if (Object.prototype.hasOwnProperty.call(keyVal[typeVal], 'name')) { |
|
||||
typeName = 'name'; |
|
||||
} |
|
||||
let key = ""; |
|
||||
key = (typeName === "") ? "No name" : ((typeName === 'name') ? keyVal[typeVal].name : keyVal[typeVal][typeName].name); |
|
||||
let conn = {}; |
|
||||
conn["enabled"] = true; |
|
||||
conn["connector"] = type; |
|
||||
conn["config"] = angular.toJson(keyVal[typeVal].config); |
|
||||
vm.configurations.connectors[key] = conn; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.getAttributeInitFromServer = (resp) => { |
|
||||
if (resp.length > 0) { |
|
||||
let attribute = angular.fromJson($window.atob(resp[0].value)); |
|
||||
for (let key in attribute) { |
|
||||
let conn = {}; |
|
||||
conn["enabled"] = false; |
|
||||
conn["connector"] = attribute[key].connector; |
|
||||
conn["config"] = angular.toJson(attribute[key].config); |
|
||||
vm.configurations.connectors[key] = conn; |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.getAttributeInitFromShared = (resp) => { |
|
||||
if (resp.length > 0) { |
|
||||
if (vm.types.gatewayLogLevel[resp[0].value.toLowerCase()]) { |
|
||||
vm.configurations.remoteLoggingLevel = resp[0].value.toUpperCase(); |
|
||||
} |
|
||||
} else { |
|
||||
vm.configurations.remoteLoggingLevel = vm.types.gatewayLogLevel.debug; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.setConfigMain = (keyVal) => { |
|
||||
if (Object.prototype.hasOwnProperty.call(keyVal, 'thingsboard')) { |
|
||||
vm.configurations.host = keyVal.thingsboard.host; |
|
||||
vm.configurations.port = keyVal.thingsboard.port; |
|
||||
vm.configurations.remoteConfiguration = keyVal.thingsboard.remoteConfiguration; |
|
||||
if (Object.prototype.hasOwnProperty.call(keyVal.thingsboard.security, 'accessToken')) { |
|
||||
vm.configurations.securityType = 'accessToken'; |
|
||||
vm.configurations.accessToken = keyVal.thingsboard.security.accessToken; |
|
||||
} else { |
|
||||
vm.configurations.securityType = 'tls'; |
|
||||
vm.configurations.caCertPath = keyVal.thingsboard.security.caCert; |
|
||||
vm.configurations.privateKeyPath = keyVal.thingsboard.security.private_key; |
|
||||
vm.configurations.certPath = keyVal.thingsboard.security.cert; |
|
||||
} |
|
||||
} |
|
||||
if (Object.prototype.hasOwnProperty.call(keyVal, 'storage') && Object.prototype.hasOwnProperty.call(keyVal.storage, 'type')) { |
|
||||
if (keyVal.storage.type === 'memory') { |
|
||||
vm.configurations.storageType = 'memoryStorage'; |
|
||||
vm.configurations.readRecordsCount = keyVal.storage.read_records_count; |
|
||||
vm.configurations.maxRecordsCount = keyVal.storage.max_records_count; |
|
||||
} else if (keyVal.storage.type === 'file') { |
|
||||
vm.configurations.storageType = 'fileStorage'; |
|
||||
vm.configurations.dataFolderPath = keyVal.storage.data_folder_path; |
|
||||
vm.configurations.maxFilesCount = keyVal.storage.max_file_count; |
|
||||
vm.configurations.readRecordsCount = keyVal.storage.read_records_count; |
|
||||
vm.configurations.maxRecordsCount = keyVal.storage.max_records_count; |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vm.setSaveTypeConfig = (itemVal) => { |
|
||||
vm.configurations.remoteConfiguration = itemVal.item; |
|
||||
}; |
|
||||
|
|
||||
vm.validFileName = (fileName) => { |
|
||||
let fileName1 = fileName.replace("_", ""); |
|
||||
let fileName2 = fileName1.replace("-", ""); |
|
||||
let fileName3 = fileName2.replace(/^\s+|\s+$/g, ''); |
|
||||
let fileName4 = fileName3.toLowerCase(); |
|
||||
return fileName4; |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
@ -1,219 +0,0 @@ |
|||||
<!-- |
|
||||
|
|
||||
Copyright © 2016-2020 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. |
|
||||
|
|
||||
--> |
|
||||
<form name="gatewayConfiguration" class="gateway-form"> |
|
||||
<md-expansion-panel-group> |
|
||||
<md-expansion-panel md-component-id="thingsboardPanelId"> |
|
||||
<md-expansion-panel-collapsed> |
|
||||
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
|
||||
<span flex></span> |
|
||||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|
||||
</md-expansion-panel-collapsed> |
|
||||
<md-expansion-panel-expanded> |
|
||||
<md-expansion-panel-header ng-click="$mdExpansionPanel('thingsboardPanelId').collapse()"> |
|
||||
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
|
||||
<span flex></span> |
|
||||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|
||||
</md-expansion-panel-header> |
|
||||
<md-expansion-panel-content> |
|
||||
<tb-gateway-config-select tb-required="true" |
|
||||
ng-model="vm.configurations.singleSelect" |
|
||||
the-form="gatewayConfiguration" |
|
||||
gateway-list="vm.gateways" |
|
||||
get_access_token="vm.getAccessToken" |
|
||||
create-device="vm.createDevice"> |
|
||||
</tb-gateway-config-select> |
|
||||
<md-input-container class="md-block"> |
|
||||
<label>{{'gateway.security-type' | translate }}</label> |
|
||||
<md-select name="securityType" ng-model="vm.configurations.securityType"> |
|
||||
<md-option ng-repeat="securityType in vm.securityTypes" ng-value="securityType.value"> |
|
||||
{{securityType.name}} |
|
||||
</md-option> |
|
||||
</md-select> |
|
||||
</md-input-container> |
|
||||
<div layout="row" class="gateway-form-row" |
|
||||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{ 'gateway.thingsboard-host' | translate }}</label> |
|
||||
<input type="text" name="host" ng-model="vm.configurations.host" required> |
|
||||
<div ng-messages="gatewayConfiguration.host.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
</div> |
|
||||
</md-input-container> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{ 'gateway.thingsboard-port' | translate }}</label> |
|
||||
<input type="number" min="1" max="65535" step="1" name="port" |
|
||||
ng-model="vm.configurations.port" required> |
|
||||
<div ng-messages="gatewayConfiguration.port.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
<div ng-message="max" translate>max</div> |
|
||||
<div ng-message="min" translate>min</div> |
|
||||
</div> |
|
||||
</md-input-container> |
|
||||
</div> |
|
||||
<div ng-if="vm.configurations.securityType=='tls'"> |
|
||||
<md-input-container class="md-block security-type"> |
|
||||
<label>{{'gateway.tls-path-ca-certificate' | translate }}</label> |
|
||||
<input type="text" ng-model="vm.configurations.caCertPath" name="caCertPath"/> |
|
||||
</md-input-container> |
|
||||
<md-input-container class="md-block"> |
|
||||
<label>{{'gateway.tls-path-private-key' | translate }}</label> |
|
||||
<input type="text" ng-model="vm.configurations.privateKeyPath" name="privateKeyPath"/> |
|
||||
</md-input-container> |
|
||||
<md-input-container class="md-block"> |
|
||||
<label>{{'gateway.tls-path-client-certificate' | translate }}</label> |
|
||||
<input type="text" ng-model="vm.configurations.certPath" name="certPath"/> |
|
||||
</md-input-container> |
|
||||
</div> |
|
||||
<md-checkbox ng-model="vm.configurations.remoteConfiguration" |
|
||||
name="remoteConfiguration" |
|
||||
ng-click="vm.setSaveTypeConfig({item: vm.configurations.remoteConfiguration})" |
|
||||
aria-label="{{ 'gateway.remote-tip' | translate }}"> |
|
||||
{{ 'gateway.remote' | translate }} |
|
||||
<md-tooltip md-direction="right">{{'gateway.remote-tip' | translate }}</md-tooltip> |
|
||||
</md-checkbox> |
|
||||
<div layout="row" class="gateway-form-row" |
|
||||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|
||||
<md-input-container class="md-block md-select-container" flex> |
|
||||
<label>{{'gateway.remote-logging-level' | translate }}</label> |
|
||||
<md-select name="loggingLevel" ng-model="vm.configurations.remoteLoggingLevel"> |
|
||||
<md-option ng-repeat="loggingLevel in vm.types.gatewayLogLevel" |
|
||||
ng-value="loggingLevel" ng-selected="$index === 5"> |
|
||||
{{loggingLevel}} |
|
||||
</md-option> |
|
||||
</md-select> |
|
||||
</md-input-container> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{'gateway.remote-logging-path-logs' | translate }}</label> |
|
||||
<input type="text" ng-model="vm.configurations.remoteLoggingPathToLogs" |
|
||||
name="remoteLoggingPathToLogs" required> |
|
||||
<div ng-messages="gatewayConfiguration.remoteLoggingPathToLogs.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
</div> |
|
||||
</md-input-container> |
|
||||
</div> |
|
||||
</md-expansion-panel-content> |
|
||||
</md-expansion-panel-expanded> |
|
||||
</md-expansion-panel> |
|
||||
<md-expansion-panel md-component-id="storagePanelId"> |
|
||||
<md-expansion-panel-collapsed> |
|
||||
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
|
||||
<span flex></span> |
|
||||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|
||||
</md-expansion-panel-collapsed> |
|
||||
<md-expansion-panel-expanded> |
|
||||
<md-expansion-panel-header ng-click="$mdExpansionPanel('storagePanelId').collapse()"> |
|
||||
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
|
||||
<span flex></span> |
|
||||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|
||||
</md-expansion-panel-header> |
|
||||
<md-expansion-panel-content> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{'gateway.storage-type' | translate }}</label> |
|
||||
<md-select required ng-model="vm.configurations.storageType"> |
|
||||
<md-option ng-repeat="storageType in vm.storageTypes" ng-value="storageType.value"> |
|
||||
{{storageType.name}} |
|
||||
</md-option> |
|
||||
</md-select> |
|
||||
</md-input-container> |
|
||||
|
|
||||
<div layout="row" class="gateway-form-row" |
|
||||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{'gateway.storage-read-time' | translate }}</label> |
|
||||
<input type="number" min="1" name="readRecordsCount" |
|
||||
ng-model='vm.configurations.readRecordsCount' required/> |
|
||||
<div ng-messages="gatewayConfiguration.readRecordsCount.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
</div> |
|
||||
</md-input-container> |
|
||||
|
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{'gateway.storage-max-time' | translate }}</label> |
|
||||
<input type="number" min="1" name="maxRecordsCount" |
|
||||
ng-model='vm.configurations.maxRecordsCount' required/> |
|
||||
<div ng-messages="gatewayConfiguration.maxRecordsCount.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
</div> |
|
||||
</md-input-container> |
|
||||
</div> |
|
||||
|
|
||||
<div layout="row" class="gateway-form-row" |
|
||||
ng-if="vm.configurations.storageType == 'fileStorage'" |
|
||||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{'gateway.storage-max-files' | translate }}</label> |
|
||||
<input type="number" min="1" name="maxFilesCount" ng-model='vm.configurations.maxFilesCount' |
|
||||
required/> |
|
||||
<div ng-messages="gatewayConfiguration.maxFilesCount.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
</div> |
|
||||
</md-input-container> |
|
||||
|
|
||||
<md-input-container class="md-block" flex> |
|
||||
<label>{{'gateway.storage-data-path' | translate }}</label> |
|
||||
<input type="text" name="dataFolderPath" ng-model='vm.configurations.dataFolderPath' |
|
||||
required/> |
|
||||
<div ng-messages="gatewayConfiguration.dataFolderPath.$error"> |
|
||||
<div ng-message="required" translate>extension.field-required</div> |
|
||||
</div> |
|
||||
</md-input-container> |
|
||||
</div> |
|
||||
</md-expansion-panel-content> |
|
||||
</md-expansion-panel-expanded> |
|
||||
</md-expansion-panel> |
|
||||
<md-expansion-panel md-component-id="connectorsPanelId"> |
|
||||
<md-expansion-panel-collapsed> |
|
||||
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
|
||||
<span flex></span> |
|
||||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|
||||
</md-expansion-panel-collapsed> |
|
||||
<md-expansion-panel-expanded> |
|
||||
<md-expansion-panel-header ng-click="$mdExpansionPanel('connectorsPanelId').collapse()"> |
|
||||
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
|
||||
<span flex></span> |
|
||||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|
||||
</md-expansion-panel-header> |
|
||||
<md-expansion-panel-content> |
|
||||
<tb-gateway-config |
|
||||
gateway-config="vm.configurations.connectors" |
|
||||
change-alignment="vm.changeAlignment"> |
|
||||
</tb-gateway-config> |
|
||||
</md-expansion-panel-content> |
|
||||
</md-expansion-panel-expanded> |
|
||||
</md-expansion-panel> |
|
||||
</md-expansion-panel-group> |
|
||||
<section layout="row" layout-align="end center" class="form-action-buttons"> |
|
||||
<md-button class="md-primary md-raised" |
|
||||
ng-click="vm.exportConfig()" |
|
||||
ng-if="!vm.configurations.remoteConfiguration" |
|
||||
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
|
||||
aria-label="{{ 'gateway.download-tip' | translate }}"> |
|
||||
{{'action.download' | translate }} |
|
||||
<md-tooltip>{{'gateway.download-tip' | translate }}</md-tooltip> |
|
||||
</md-button> |
|
||||
|
|
||||
<md-button class="md-primary md-raised" |
|
||||
ng-click="vm.saveAttributeConfig()" |
|
||||
ng-if="vm.configurations.remoteConfiguration" |
|
||||
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
|
||||
aria-label="{{ 'gateway.save-tip' | translate }}"> |
|
||||
{{'action.save' | translate }} |
|
||||
<md-tooltip ng-if="vm.configurations.remoteConfiguration">{{'gateway.save-tip' | translate }}</md-tooltip> |
|
||||
</md-button> |
|
||||
</section> |
|
||||
</form> |
|
||||
@ -0,0 +1,170 @@ |
|||||
|
/* |
||||
|
* Copyright © 2016-2020 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 './gateway-config.scss'; |
||||
|
|
||||
|
/* eslint-disable import/no-unresolved, import/default */ |
||||
|
|
||||
|
import gatewayConfigTemplate from './gateway-config.tpl.html'; |
||||
|
import gatewayConfigDialogTemplate from './gateway-config-dialog.tpl.html'; |
||||
|
import beautify from "js-beautify"; |
||||
|
|
||||
|
/* eslint-enable import/no-unresolved, import/default */ |
||||
|
const js_beautify = beautify.js; |
||||
|
|
||||
|
export default angular.module('thingsboard.directives.gatewayConfig', []) |
||||
|
.directive('tbGatewayConfig', GatewayConfig) |
||||
|
.name; |
||||
|
|
||||
|
/*@ngInject*/ |
||||
|
function GatewayConfig() { |
||||
|
return { |
||||
|
restrict: "E", |
||||
|
scope: true, |
||||
|
bindToController: { |
||||
|
disabled: '=ngDisabled', |
||||
|
gatewayConfig: '=', |
||||
|
changeAlignment: '=', |
||||
|
theForm: '=' |
||||
|
}, |
||||
|
controller: GatewayConfigController, |
||||
|
controllerAs: 'vm', |
||||
|
templateUrl: gatewayConfigTemplate |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/*@ngInject*/ |
||||
|
function GatewayConfigController($scope, $document, $mdDialog, $mdUtil, $window, types) { |
||||
|
let vm = this; |
||||
|
vm.types = types; |
||||
|
|
||||
|
vm.removeConnector = (index) => { |
||||
|
if (index > -1) { |
||||
|
vm.gatewayConfig.splice(index, 1); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
vm.addNewConnector = () => { |
||||
|
vm.gatewayConfig.push({ |
||||
|
enabled: false, |
||||
|
configType: '', |
||||
|
config: {}, |
||||
|
name: '' |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
vm.openConfigDialog = ($event, index, config, typeName) => { |
||||
|
if ($event) { |
||||
|
$event.stopPropagation(); |
||||
|
} |
||||
|
$mdDialog.show({ |
||||
|
controller: GatewayDialogController, |
||||
|
controllerAs: 'vm', |
||||
|
templateUrl: gatewayConfigDialogTemplate, |
||||
|
parent: angular.element($document[0].body), |
||||
|
locals: { |
||||
|
config: config, |
||||
|
typeName: typeName |
||||
|
}, |
||||
|
targetEvent: $event, |
||||
|
fullscreen: true, |
||||
|
multiple: true, |
||||
|
}).then(function (config) { |
||||
|
if (config && index > -1) { |
||||
|
vm.gatewayConfig[index].config = config; |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
vm.changeConnectorType = (connector) => { |
||||
|
for (let gatewayConfigTypeKey in types.gatewayConfigType) { |
||||
|
if (types.gatewayConfigType[gatewayConfigTypeKey].value === connector.configType) { |
||||
|
if (!connector.name) { |
||||
|
connector.name = generateConnectorName(types.gatewayConfigType[gatewayConfigTypeKey].name, 0); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
vm.changeConnectorName = (connector, currentConnectorIndex) => { |
||||
|
connector.name = validateConnectorName(connector.name, 0, currentConnectorIndex); |
||||
|
}; |
||||
|
|
||||
|
function generateConnectorName(name, index) { |
||||
|
let newKeyName = index ? name + index : name; |
||||
|
let indexRes = vm.gatewayConfig.findIndex((element) => element.name === newKeyName); |
||||
|
return indexRes === -1 ? newKeyName : generateConnectorName(name, ++index); |
||||
|
} |
||||
|
|
||||
|
function validateConnectorName(name, index, currentConnectorIndex) { |
||||
|
for (let i = 0; i < vm.gatewayConfig.length; i++) { |
||||
|
let nameEq = (index === 0) ? name : name + index; |
||||
|
if (i !== currentConnectorIndex && vm.gatewayConfig[i].name === nameEq) { |
||||
|
index++; |
||||
|
validateConnectorName(name, index, currentConnectorIndex); |
||||
|
} |
||||
|
} |
||||
|
return (index === 0) ? name : name + index; |
||||
|
} |
||||
|
|
||||
|
vm.validateJSON = (config) => { |
||||
|
return angular.equals({}, config); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/*@ngInject*/ |
||||
|
function GatewayDialogController($scope, $mdDialog, $document, $window, config, typeName) { |
||||
|
let vm = this; |
||||
|
vm.config = js_beautify(angular.toJson(config), {indent_size: 4}); |
||||
|
vm.typeName = typeName; |
||||
|
vm.configAreaOptions = { |
||||
|
useWrapMode: true, |
||||
|
mode: 'json', |
||||
|
advanced: { |
||||
|
enableSnippets: true, |
||||
|
enableBasicAutocompletion: true, |
||||
|
enableLiveAutocompletion: true |
||||
|
}, |
||||
|
onLoad: function (_ace) { |
||||
|
_ace.$blockScrolling = 1; |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
vm.validateConfig = (model, editorName) => { |
||||
|
if (model && model.length) { |
||||
|
try { |
||||
|
angular.fromJson(model); |
||||
|
$scope.theForm[editorName].$setValidity('config', true); |
||||
|
} catch (e) { |
||||
|
$scope.theForm[editorName].$setValidity('config', false); |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
vm.save = () => { |
||||
|
$mdDialog.hide(angular.fromJson(vm.config)); |
||||
|
}; |
||||
|
|
||||
|
vm.cancel = () => { |
||||
|
$mdDialog.hide(); |
||||
|
}; |
||||
|
|
||||
|
vm.beautifyJson = () => { |
||||
|
vm.config = js_beautify(vm.config, {indent_size: 4}); |
||||
|
}; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,81 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2020 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. |
||||
|
|
||||
|
--> |
||||
|
<section name="gatewayConfig" layout="column" class="gateway-config"> |
||||
|
<section layout="row" ng-form="gatewayConfig_{{$index}}" ng-repeat="connector in vm.gatewayConfig track by $index"> |
||||
|
<div layout="column" layout-align="center start" class="gateway-config-row"> |
||||
|
<md-switch ng-model="connector.enabled" ng-disabled="gatewayConfig_{{$index}}.$invalid || vm.validateJSON(connector.config)" |
||||
|
aria-label="{{ 'gateway.connector-enabled' | translate }}"> |
||||
|
</md-switch> |
||||
|
</div> |
||||
|
<div layout="row" flex class="gateway-config-row" |
||||
|
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{'gateway.connector-type' | translate }}</label> |
||||
|
<md-select name="connectorType" |
||||
|
ng-change="vm.changeConnectorType(connector)" |
||||
|
aria-label="{{ 'gateway.gateway.connector-type' | translate }}" |
||||
|
ng-model="connector.configType" required> |
||||
|
<md-option ng-repeat="configType in vm.types.gatewayConfigType" ng-value="configType.value"> |
||||
|
{{configType.value}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
<div ng-messages="vm.theForm.connectorType.$error"> |
||||
|
<div ng-message="required" translate>gateway.connector-type-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<input placeholder="{{'gateway.connector-name' | translate }}" |
||||
|
ng-model-options="{ updateOn: 'blur' }" |
||||
|
ng-change="vm.changeConnectorName(connector, $index)" name="connectorName" ng-model="connector.name" required/> |
||||
|
<div ng-messages="vm.theForm.connectorName.$error"> |
||||
|
<div ng-message="required" translate>gateway.connector-name-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
<div layout="row" layout-align="end center" class="action-buttons" |
||||
|
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
||||
|
<md-button class="md-icon-button md-mini" ng-click="vm.openConfigDialog($event, $index, connector.config, connector.name)" |
||||
|
aria-label="{{ 'gateway.update-config' | translate }}" |
||||
|
ng-class="{'md-warn': vm.validateJSON(connector.config)}"> |
||||
|
<md-icon class="material-icons">more_horiz</md-icon> |
||||
|
<md-tooltip md-direction="top"> |
||||
|
{{ 'gateway.update-config' | translate }} |
||||
|
</md-tooltip> |
||||
|
</md-button> |
||||
|
<md-button class="md-icon-button md-mini" ng-click="vm.removeConnector($index)" |
||||
|
aria-label="{{ 'gateway.delete' | translate }}"> |
||||
|
<md-icon class="material-icons">close</md-icon> |
||||
|
<md-tooltip md-direction="top"> |
||||
|
{{ 'gateway.delete' | translate }} |
||||
|
</md-tooltip> |
||||
|
</md-button> |
||||
|
</div> |
||||
|
</section> |
||||
|
<span ng-show="!vm.gatewayConfig.length" |
||||
|
layout-align="center center" ng-class="{'disabled': vm.disabled}" |
||||
|
class="no-data-found" translate>{{'gateway.no-connectors'}}</span> |
||||
|
<div> |
||||
|
<md-button class="md-raised" ng-click="vm.addNewConnector()" |
||||
|
aria-label="{{ 'gateway.connector-add' | translate }}"> |
||||
|
<md-tooltip md-direction="top"> |
||||
|
{{ 'gateway.connector-add' | translate }} |
||||
|
</md-tooltip> |
||||
|
<span translate>action.add</span> |
||||
|
</md-button> |
||||
|
</div> |
||||
|
</section > |
||||
@ -0,0 +1,467 @@ |
|||||
|
/* |
||||
|
* Copyright © 2016-2020 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 './gateway-form.scss'; |
||||
|
/* eslint-disable import/no-unresolved, import/default */ |
||||
|
|
||||
|
import gatewayFormTemplate from './gateway-form.tpl.html'; |
||||
|
|
||||
|
/* eslint-enable import/no-unresolved, import/default */ |
||||
|
|
||||
|
export default angular.module('thingsboard.directives.gatewayForm', []) |
||||
|
.directive('tbGatewayForm', GatewayForm) |
||||
|
.name; |
||||
|
|
||||
|
/*@ngInject*/ |
||||
|
function GatewayForm() { |
||||
|
return { |
||||
|
restrict: "E", |
||||
|
scope: true, |
||||
|
bindToController: { |
||||
|
formId: '=', |
||||
|
ctx: '=' |
||||
|
}, |
||||
|
controller: GatewayFormController, |
||||
|
controllerAs: 'vm', |
||||
|
templateUrl: gatewayFormTemplate |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
/*@ngInject*/ |
||||
|
function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, toast, importExport, attributeService, deviceService, userService, $mdDialog, $mdUtil, types, $window, $q, entityService, utils, $translate) { |
||||
|
let vm = this; |
||||
|
const currentConfigurationAttribute = "current_configuration"; |
||||
|
const configurationDraftsAttribute = "configuration_drafts"; |
||||
|
const configurationAttribute = "configuration"; |
||||
|
const remoteLoggingLevelAttribute = "RemoteLoggingLevel"; |
||||
|
|
||||
|
const templateLogsConfig = '[loggers]}}keys=root, service, connector, converter, tb_connection, storage, extension}}[handlers]}}keys=consoleHandler, serviceHandler, connectorHandler, converterHandler, tb_connectionHandler, storageHandler, extensionHandler}}[formatters]}}keys=LogFormatter}}[logger_root]}}level=ERROR}}handlers=consoleHandler}}[logger_connector]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=connector}}[logger_storage]}}level={ERROR}}}handlers=storageHandler}}formatter=LogFormatter}}qualname=storage}}[logger_tb_connection]}}level={ERROR}}}handlers=tb_connectionHandler}}formatter=LogFormatter}}qualname=tb_connection}}[logger_service]}}level={ERROR}}}handlers=serviceHandler}}formatter=LogFormatter}}qualname=service}}[logger_converter]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=converter}}[logger_extension]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=extension}}[handler_consoleHandler]}}class=StreamHandler}}level={ERROR}}}formatter=LogFormatter}}args=(sys.stdout,)}}[handler_connectorHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}connector.log", "d", 1, 7,)}}[handler_storageHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}storage.log", "d", 1, 7,)}}[handler_serviceHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}service.log", "d", 1, 7,)}}[handler_converterHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}converter.log", "d", 1, 3,)}}[handler_extensionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}extension.log", "d", 1, 3,)}}[handler_tb_connectionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}tb_connection.log", "d", 1, 3,)}}[formatter_LogFormatter]}}format="%(asctime)s - %(levelname)s - [%(filename)s] - %(module)s - %(lineno)d - %(message)s" }}datefmt="%Y-%m-%d %H:%M:%S"'; |
||||
|
|
||||
|
vm.types = types; |
||||
|
|
||||
|
vm.configurations = { |
||||
|
gateway: '', |
||||
|
host: $document[0].domain, |
||||
|
port: 1883, |
||||
|
remoteConfiguration: true, |
||||
|
accessToken: '', |
||||
|
storageType: "memoryStorage", |
||||
|
readRecordsCount: 100, |
||||
|
maxRecordsCount: 10000, |
||||
|
dataFolderPath: './data/', |
||||
|
maxFilesCount: 5, |
||||
|
securityType: "accessToken", |
||||
|
caCertPath: '/etc/thingsboard-gateway/ca.pem', |
||||
|
privateKeyPath: '/etc/thingsboard-gateway/privateKey.pem', |
||||
|
certPath: '/etc/thingsboard-gateway/certificate.pem', |
||||
|
connectors: [], |
||||
|
remoteLoggingLevel: "DEBUG", |
||||
|
remoteLoggingPathToLogs: './logs/' |
||||
|
}; |
||||
|
|
||||
|
let archiveFileName = ''; |
||||
|
let gatewayNameExists = ''; |
||||
|
let successfulSaved = ''; |
||||
|
|
||||
|
vm.securityTypes = [{ |
||||
|
name: 'gateway.security-types.access-token', |
||||
|
value: 'accessToken' |
||||
|
}, { |
||||
|
name: 'gateway.security-types.tls', |
||||
|
value: 'tls' |
||||
|
}]; |
||||
|
|
||||
|
vm.storageTypes = [{ |
||||
|
name: 'gateway.storage-types.memory-storage', |
||||
|
value: 'memoryStorage' |
||||
|
}, { |
||||
|
name: 'gateway.storage-types.file-storage', |
||||
|
value: 'fileStorage' |
||||
|
}]; |
||||
|
|
||||
|
$scope.$watch('vm.ctx', function () { |
||||
|
if (vm.ctx ) { |
||||
|
vm.settings = vm.ctx.settings; |
||||
|
vm.widgetConfig = vm.ctx.widgetConfig; |
||||
|
initializeConfig(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
$scope.$on('gateway-form-resize', function (event, formId) { |
||||
|
if (vm.formId == formId) { |
||||
|
updateWidgetDisplaying(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
function updateWidgetDisplaying() { |
||||
|
vm.changeAlignment = (vm.ctx.$container[0].offsetWidth <= 425); |
||||
|
} |
||||
|
|
||||
|
function initWidgetSettings() { |
||||
|
let widgetTitle; |
||||
|
if (vm.settings.widgetTitle && vm.settings.widgetTitle.length) { |
||||
|
widgetTitle = utils.customTranslation(vm.settings.widgetTitle, vm.settings.widgetTitle); |
||||
|
} else { |
||||
|
widgetTitle = $translate.instant('gateway.gateway'); |
||||
|
} |
||||
|
vm.ctx.widgetTitle = widgetTitle; |
||||
|
|
||||
|
archiveFileName = vm.settings.archiveFileName && vm.settings.archiveFileName.length ? vm.settings.archiveFileName : 'gatewayConfiguration'; |
||||
|
gatewayNameExists = utils.customTranslation(vm.settings.deviceNameExist, vm.settings.deviceNameExist) || $translate.instant('gateway.gateway-exists'); |
||||
|
successfulSaved = utils.customTranslation(vm.settings.successfulSave, vm.settings.successfulSave) || $translate.instant('gateway.gateway-saved'); |
||||
|
} |
||||
|
|
||||
|
function initializeConfig() { |
||||
|
updateWidgetDisplaying(); |
||||
|
initWidgetSettings(); |
||||
|
getGatewaysList(true); |
||||
|
} |
||||
|
|
||||
|
vm.getAccessToken = (deviceId) => { |
||||
|
if (deviceId.id) { |
||||
|
getDeviceCredentials(deviceId.id); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
vm.collapsePanel = function (panelId) { |
||||
|
$mdExpansionPanel(panelId).collapse(); |
||||
|
}; |
||||
|
|
||||
|
function getDeviceCredentials(deviceId) { |
||||
|
return deviceService.getDeviceCredentials(deviceId).then( |
||||
|
(deviceCredentials) => { |
||||
|
vm.configurations.accessToken = deviceCredentials.credentialsId; |
||||
|
getAttributes(); |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
vm.createDevice = (deviceObj) => { |
||||
|
deviceService.findByName(deviceObj.name, {ignoreErrors: true}) |
||||
|
.then( |
||||
|
function () { |
||||
|
toast.showError(gatewayNameExists, angular.element('.gateway-form'),'top left'); |
||||
|
}, |
||||
|
function () { |
||||
|
if(vm.settings.gatewayType && vm.settings.gatewayType.length){ |
||||
|
deviceObj.type = vm.settings.gatewayType; |
||||
|
} |
||||
|
deviceService.saveDevice(deviceObj).then( |
||||
|
(device) => { |
||||
|
getDeviceCredentials(device.id.id).then(() =>{ |
||||
|
getGatewaysList(); |
||||
|
}); |
||||
|
} |
||||
|
); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
vm.saveAttributeConfig = () => { |
||||
|
$q.all([ |
||||
|
saveAttribute(configurationAttribute, $window.btoa(angular.toJson(getGatewayConfigJSON())), types.attributesScope.shared.value), |
||||
|
saveAttribute(configurationDraftsAttribute, $window.btoa(angular.toJson(getDraftConnectorJSON())), types.attributesScope.server.value), |
||||
|
saveAttribute(remoteLoggingLevelAttribute, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value) |
||||
|
]).then(() =>{ |
||||
|
toast.showSuccess(successfulSaved, 2000, angular.element('.gateway-form'),'top left'); |
||||
|
}) |
||||
|
}; |
||||
|
|
||||
|
function getAttributes() { |
||||
|
let promises = []; |
||||
|
promises.push(getAttribute(currentConfigurationAttribute, types.attributesScope.client.value)); |
||||
|
promises.push(getAttribute(configurationDraftsAttribute, types.attributesScope.server.value)); |
||||
|
promises.push(getAttribute(remoteLoggingLevelAttribute, types.attributesScope.shared.value)); |
||||
|
$q.all(promises).then((response) => { |
||||
|
processCurrentConfiguration(response[0]); |
||||
|
processConfigurationDrafts(response[1]); |
||||
|
processLoggingLevel(response[2]); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getAttribute(attributeName, attributeScope) { |
||||
|
return attributeService.getEntityAttributesValues(vm.configurations.gateway.id.entityType, vm.configurations.gateway.id.id, attributeScope, attributeName); |
||||
|
} |
||||
|
|
||||
|
function saveAttribute(attributeName, attributeValue, attributeScope) { |
||||
|
let attributes = [{ |
||||
|
key: attributeName, |
||||
|
value: attributeValue |
||||
|
}]; |
||||
|
return attributeService.saveEntityAttributes(vm.configurations.gateway.id.entityType, vm.configurations.gateway.id.id, attributeScope, attributes); |
||||
|
} |
||||
|
|
||||
|
vm.exportConfig = () => { |
||||
|
let filesZip = {}; |
||||
|
filesZip["tb_gateway.yaml"] = generateYAMLConfigurationFile(); |
||||
|
generateConfigConnectorFiles(filesZip); |
||||
|
generateLogConfigFile(filesZip); |
||||
|
importExport.exportJSZip(filesZip, archiveFileName); |
||||
|
saveAttribute(remoteLoggingLevelAttribute, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value); |
||||
|
}; |
||||
|
|
||||
|
function generateYAMLConfigurationFile() { |
||||
|
let config; |
||||
|
config = 'thingsboard:\n'; |
||||
|
config += ' host: ' + vm.configurations.host + '\n'; |
||||
|
config += ' remoteConfiguration: ' + vm.configurations.remoteConfiguration + '\n'; |
||||
|
config += ' port: ' + vm.configurations.port + '\n'; |
||||
|
config += ' security:\n'; |
||||
|
if (vm.configurations.securityType === 'accessToken') { |
||||
|
config += ' access-token: ' + vm.configurations.accessToken + '\n'; |
||||
|
} else if (vm.configurations.securityType === 'tls') { |
||||
|
config += ' ca_cert: ' + vm.configurations.caCertPath + '\n'; |
||||
|
config += ' privateKey: ' + vm.configurations.privateKeyPath + '\n'; |
||||
|
config += ' cert: ' + vm.configurations.certPath + '\n'; |
||||
|
} |
||||
|
config += 'storage:\n'; |
||||
|
if (vm.configurations.storageType === 'memoryStorage') { |
||||
|
config += ' type: memory\n'; |
||||
|
config += ' read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
||||
|
config += ' max_records_count: ' + vm.configurations.maxRecordsCount + '\n'; |
||||
|
} else if (vm.configurations.storageType === 'fileStorage') { |
||||
|
config += ' type: file\n'; |
||||
|
config += ' data_folder_path: ' + vm.configurations.dataFolderPath + '\n'; |
||||
|
config += ' max_file_count: ' + vm.configurations.maxFilesCount + '\n'; |
||||
|
config += ' max_read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
||||
|
config += ' max_records_per_file: ' + vm.configurations.maxRecordsCount + '\n'; |
||||
|
} |
||||
|
config += 'connectors:\n'; |
||||
|
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
||||
|
if (vm.configurations.connectors[i].enabled) { |
||||
|
config += ' -\n'; |
||||
|
config += ' name: ' + vm.configurations.connectors[i].name + '\n'; |
||||
|
config += ' type: ' + vm.configurations.connectors[i].configType + '\n'; |
||||
|
config += ' configuration: ' + generateFileName(vm.configurations.connectors[i].name) + '\n'; |
||||
|
} |
||||
|
} |
||||
|
return config; |
||||
|
} |
||||
|
|
||||
|
function generateConfigConnectorFiles(fileZipAdd) { |
||||
|
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
||||
|
if (vm.configurations.connectors[i].enabled) { |
||||
|
fileZipAdd[generateFileName(vm.configurations.connectors[i].name)] = angular.toJson(vm.configurations.connectors[i].config); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function generateLogConfigFile(fileZipAdd) { |
||||
|
fileZipAdd["logs.conf"] = getLogsConfig(); |
||||
|
} |
||||
|
|
||||
|
function getLogsConfig() { |
||||
|
return templateLogsConfig |
||||
|
.replace(/{ERROR}/g, vm.configurations.remoteLoggingLevel) |
||||
|
.replace(/{.\/logs\/}/g, vm.configurations.remoteLoggingPathToLogs); |
||||
|
} |
||||
|
|
||||
|
function getGatewayConfigJSON() { |
||||
|
let gatewayConfig = {}; |
||||
|
gatewayConfig["thingsboard"] = gatewayMainConfigJSON(); |
||||
|
gatewayConnectorConfigJSON(gatewayConfig); |
||||
|
return gatewayConfig; |
||||
|
} |
||||
|
|
||||
|
function gatewayMainConfigJSON() { |
||||
|
let configuration = {}; |
||||
|
|
||||
|
let thingsBoard = {}; |
||||
|
thingsBoard.host = vm.configurations.host; |
||||
|
thingsBoard.remoteConfiguration = vm.configurations.remoteConfiguration; |
||||
|
thingsBoard.port = vm.configurations.port; |
||||
|
let security = {}; |
||||
|
if (vm.configurations.securityType === 'accessToken') { |
||||
|
security.accessToken = (vm.configurations.accessToken) ? vm.configurations.accessToken : "" |
||||
|
} else { |
||||
|
security.caCert = vm.configurations.caCertPath; |
||||
|
security.privateKey = vm.configurations.privateKeyPath; |
||||
|
security.cert = vm.configurations.certPath; |
||||
|
} |
||||
|
thingsBoard.security = security; |
||||
|
configuration.thingsboard = thingsBoard; |
||||
|
|
||||
|
let storage = {}; |
||||
|
if (vm.configurations.storageType === 'memoryStorage') { |
||||
|
storage.type = "memory"; |
||||
|
storage.read_records_count = vm.configurations.readRecordsCount; |
||||
|
storage.max_records_count = vm.configurations.maxRecordsCount; |
||||
|
} else if (vm.configurations.storageType === 'fileStorage') { |
||||
|
storage.type = "file"; |
||||
|
storage.data_folder_path = vm.configurations.dataFolderPath; |
||||
|
storage.max_file_count = vm.configurations.maxFilesCount; |
||||
|
storage.max_read_records_count = vm.configurations.readRecordsCount; |
||||
|
storage.max_records_per_file = vm.configurations.maxRecordsCount; |
||||
|
} |
||||
|
configuration.storage = storage; |
||||
|
|
||||
|
let connectors = []; |
||||
|
for (let i = 0; i < vm.configurations.connectors.length; i++) { |
||||
|
if (vm.configurations.connectors[i].enabled) { |
||||
|
let connector = { |
||||
|
configuration: generateFileName(vm.configurations.connectors[i].name), |
||||
|
name: vm.configurations.connectors[i].name, |
||||
|
type: vm.configurations.connectors[i].configType |
||||
|
}; |
||||
|
connectors.push(connector); |
||||
|
} |
||||
|
} |
||||
|
configuration.connectors = connectors; |
||||
|
|
||||
|
configuration.logs = $window.btoa(getLogsConfig()); |
||||
|
|
||||
|
return configuration; |
||||
|
} |
||||
|
|
||||
|
function gatewayConnectorConfigJSON(gatewayConfiguration) { |
||||
|
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
||||
|
if (vm.configurations.connectors[i].enabled) { |
||||
|
let typeConnector = vm.configurations.connectors[i].configType; |
||||
|
if(!angular.isArray(gatewayConfiguration[typeConnector])){ |
||||
|
gatewayConfiguration[typeConnector] = []; |
||||
|
} |
||||
|
|
||||
|
let connectorConfig = { |
||||
|
name: vm.configurations.connectors[i].name, |
||||
|
config: vm.configurations.connectors[i].config |
||||
|
}; |
||||
|
gatewayConfiguration[typeConnector].push(connectorConfig); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function getDraftConnectorJSON() { |
||||
|
let draftConnector = {}; |
||||
|
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
||||
|
if (!vm.configurations.connectors[i].enabled) { |
||||
|
let connector = { |
||||
|
connector: vm.configurations.connectors[i].configType, |
||||
|
config: vm.configurations.connectors[i].config |
||||
|
}; |
||||
|
draftConnector[vm.configurations.connectors[i].name] = connector; |
||||
|
} |
||||
|
} |
||||
|
return draftConnector; |
||||
|
} |
||||
|
|
||||
|
function getGatewaysList(firstInit) { |
||||
|
vm.gateways = []; |
||||
|
entityService.getEntitiesByNameFilter(types.entityType.device, "", -1).then((devices) => { |
||||
|
for (let i = 0; i < devices.length; i++) { |
||||
|
const device = devices[i]; |
||||
|
if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { |
||||
|
vm.gateways.push(device); |
||||
|
if (firstInit && vm.gateways.length && device.name === vm.gateways[0].name) { |
||||
|
vm.configurations.gateway = device; |
||||
|
vm.getAccessToken(device.id); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function processCurrentConfiguration(response) { |
||||
|
if (response.length > 0) { |
||||
|
vm.configurations.connectors = []; |
||||
|
let attribute = angular.fromJson($window.atob(response[0].value)); |
||||
|
for (var attributeKey in attribute) { |
||||
|
let keyValue = attribute[attributeKey]; |
||||
|
if (attributeKey === "thingsboard") { |
||||
|
if (keyValue !== null && Object.keys(keyValue).length > 0) { |
||||
|
setConfigGateway(keyValue); |
||||
|
} |
||||
|
} else { |
||||
|
for (let connectorType in keyValue) { |
||||
|
let name = "No name"; |
||||
|
if (Object.prototype.hasOwnProperty.call(keyValue[connectorType], 'name')) { |
||||
|
name = keyValue[connectorType].name ; |
||||
|
} |
||||
|
let connector = { |
||||
|
enabled: true, |
||||
|
configType: attributeKey, |
||||
|
config: keyValue[connectorType].config, |
||||
|
name: name |
||||
|
}; |
||||
|
vm.configurations.connectors.push(connector); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function processConfigurationDrafts(response) { |
||||
|
if (response.length > 0) { |
||||
|
let attribute = angular.fromJson($window.atob(response[0].value)); |
||||
|
for (let key in attribute) { |
||||
|
let connector = { |
||||
|
enabled: false, |
||||
|
configType: attribute[key].connector, |
||||
|
config: attribute[key].config, |
||||
|
name: key |
||||
|
}; |
||||
|
vm.configurations.connectors.push(connector); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function processLoggingLevel(response) { |
||||
|
if (response.length > 0) { |
||||
|
if (vm.types.gatewayLogLevel[response[0].value.toLowerCase()]) { |
||||
|
vm.configurations.remoteLoggingLevel = response[0].value.toUpperCase(); |
||||
|
} |
||||
|
} else { |
||||
|
vm.configurations.remoteLoggingLevel = vm.types.gatewayLogLevel.debug; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function setConfigGateway(keyValue) { |
||||
|
if (Object.prototype.hasOwnProperty.call(keyValue, 'thingsboard')) { |
||||
|
vm.configurations.host = keyValue.thingsboard.host; |
||||
|
vm.configurations.port = keyValue.thingsboard.port; |
||||
|
vm.configurations.remoteConfiguration = keyValue.thingsboard.remoteConfiguration; |
||||
|
if (Object.prototype.hasOwnProperty.call(keyValue.thingsboard.security, 'accessToken')) { |
||||
|
vm.configurations.securityType = 'accessToken'; |
||||
|
vm.configurations.accessToken = keyValue.thingsboard.security.accessToken; |
||||
|
} else { |
||||
|
vm.configurations.securityType = 'tls'; |
||||
|
vm.configurations.caCertPath = keyValue.thingsboard.security.caCert; |
||||
|
vm.configurations.privateKeyPath = keyValue.thingsboard.security.private_key; |
||||
|
vm.configurations.certPath = keyValue.thingsboard.security.cert; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (Object.prototype.hasOwnProperty.call(keyValue, 'storage') && Object.prototype.hasOwnProperty.call(keyValue.storage, 'type')) { |
||||
|
if (keyValue.storage.type === 'memory') { |
||||
|
vm.configurations.storageType = 'memoryStorage'; |
||||
|
vm.configurations.readRecordsCount = keyValue.storage.read_records_count; |
||||
|
vm.configurations.maxRecordsCount = keyValue.storage.max_records_count; |
||||
|
} else if (keyValue.storage.type === 'file') { |
||||
|
vm.configurations.storageType = 'fileStorage'; |
||||
|
vm.configurations.dataFolderPath = keyValue.storage.data_folder_path; |
||||
|
vm.configurations.maxFilesCount = keyValue.storage.max_file_count; |
||||
|
vm.configurations.readRecordsCount = keyValue.storage.read_records_count; |
||||
|
vm.configurations.maxRecordsCount = keyValue.storage.max_records_count; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function generateFileName(fileName) { |
||||
|
return fileName.replace("_", "") |
||||
|
.replace("-", "") |
||||
|
.replace(/^\s+|\s+/g, '') |
||||
|
.toLowerCase() + '.json'; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -0,0 +1,227 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2020 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. |
||||
|
|
||||
|
--> |
||||
|
<md-content md-scroll-y layout="column" class="gateway-form"> |
||||
|
<form name="gatewayConfiguration"> |
||||
|
<md-expansion-panel-group> |
||||
|
<md-expansion-panel md-component-id="thingsboardPanelId"> |
||||
|
<md-expansion-panel-collapsed> |
||||
|
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
||||
|
<span flex></span> |
||||
|
<md-expansion-panel-icon></md-expansion-panel-icon> |
||||
|
</md-expansion-panel-collapsed> |
||||
|
<md-expansion-panel-expanded> |
||||
|
<md-expansion-panel-header ng-click="vm.collapsePanel('thingsboardPanelId')"> |
||||
|
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
||||
|
<span flex></span> |
||||
|
<md-expansion-panel-icon></md-expansion-panel-icon> |
||||
|
</md-expansion-panel-header> |
||||
|
<md-expansion-panel-content> |
||||
|
<tb-gateway-config-select tb-required="true" |
||||
|
ng-model="vm.configurations.gateway" |
||||
|
the-form="gatewayConfiguration" |
||||
|
gateway-list="vm.gateways" |
||||
|
get_access_token="vm.getAccessToken" |
||||
|
create-device="vm.createDevice"> |
||||
|
</tb-gateway-config-select> |
||||
|
<md-input-container class="md-block"> |
||||
|
<label>{{'gateway.security-type' | translate }}</label> |
||||
|
<md-select name="securityType" ng-model="vm.configurations.securityType" required> |
||||
|
<md-option ng-repeat="securityType in vm.securityTypes" ng-value="securityType.value"> |
||||
|
{{securityType.name | translate}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
</md-input-container> |
||||
|
<div layout="row" class="gateway-form-row" |
||||
|
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{ 'gateway.thingsboard-host' | translate }}</label> |
||||
|
<input type="text" name="host" ng-model="vm.configurations.host" required> |
||||
|
<div ng-messages="gatewayConfiguration.host.$error"> |
||||
|
<div ng-message="required" translate>gateway.thingsboard-host-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{ 'gateway.thingsboard-port' | translate }}</label> |
||||
|
<input type="number" min="1" max="65535" ng-pattern="/^-?[0-9]+$/" name="port" |
||||
|
ng-model="vm.configurations.port" required> |
||||
|
<div ng-messages="gatewayConfiguration.port.$error"> |
||||
|
<div ng-message="required" translate>gateway.thingsboard-port-required</div> |
||||
|
<div ng-message="max" translate>gateway.thingsboard-port-max</div> |
||||
|
<div ng-message="min" translate>gateway.thingsboard-port-min</div> |
||||
|
<div ng-message="pattern" translate>gateway.thingsboard-port-pattern</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
<div ng-if="vm.configurations.securityType=='tls'"> |
||||
|
<md-input-container class="md-block security-type"> |
||||
|
<label>{{'gateway.tls-path-ca-certificate' | translate }}</label> |
||||
|
<input type="text" ng-model="vm.configurations.caCertPath" name="caCertPath" /> |
||||
|
</md-input-container> |
||||
|
<md-input-container class="md-block"> |
||||
|
<label>{{'gateway.tls-path-private-key' | translate }}</label> |
||||
|
<input type="text" ng-model="vm.configurations.privateKeyPath" name="privateKeyPath" /> |
||||
|
</md-input-container> |
||||
|
<md-input-container class="md-block"> |
||||
|
<label>{{'gateway.tls-path-client-certificate' | translate }}</label> |
||||
|
<input type="text" ng-model="vm.configurations.certPath" name="certPath" /> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
<md-checkbox ng-model="vm.configurations.remoteConfiguration" |
||||
|
name="remoteConfiguration" |
||||
|
aria-label="{{ 'gateway.remote-remote' | translate }}"> |
||||
|
{{ 'gateway.remote' | translate }} |
||||
|
</md-checkbox> |
||||
|
<div layout="row" class="gateway-form-row" |
||||
|
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
||||
|
<md-input-container class="md-block md-select-container" flex> |
||||
|
<label>{{'gateway.remote-logging-level' | translate }}</label> |
||||
|
<md-select name="loggingLevel" ng-model="vm.configurations.remoteLoggingLevel"> |
||||
|
<md-option ng-repeat="logLevel in vm.types.gatewayLogLevel" |
||||
|
ng-value="logLevel" ng-selected="$index === 5"> |
||||
|
{{logLevel}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
</md-input-container> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{'gateway.path-logs' | translate }}</label> |
||||
|
<input type="text" ng-model="vm.configurations.remoteLoggingPathToLogs" |
||||
|
name="remoteLoggingPathToLogs" required> |
||||
|
<div ng-messages="gatewayConfiguration.remoteLoggingPathToLogs.$error"> |
||||
|
<div ng-message="required" translate>gateway.path-logs-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
</md-expansion-panel-content> |
||||
|
</md-expansion-panel-expanded> |
||||
|
</md-expansion-panel> |
||||
|
<md-expansion-panel md-component-id="storagePanelId"> |
||||
|
<md-expansion-panel-collapsed> |
||||
|
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
||||
|
<span flex></span> |
||||
|
<md-expansion-panel-icon></md-expansion-panel-icon> |
||||
|
</md-expansion-panel-collapsed> |
||||
|
<md-expansion-panel-expanded> |
||||
|
<md-expansion-panel-header ng-click="vm.collapsePanel('storagePanelId')"> |
||||
|
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
||||
|
<span flex></span> |
||||
|
<md-expansion-panel-icon></md-expansion-panel-icon> |
||||
|
</md-expansion-panel-header> |
||||
|
<md-expansion-panel-content> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{'gateway.storage-type' | translate }}</label> |
||||
|
<md-select required ng-model="vm.configurations.storageType"> |
||||
|
<md-option ng-repeat="storageType in vm.storageTypes" ng-value="storageType.value"> |
||||
|
{{storageType.name | translate}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<div layout="row" class="gateway-form-row" |
||||
|
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{'gateway.storage-pack-size' | translate }}</label> |
||||
|
<input type="number" min="1" name="readRecordsCount" ng-pattern="/^-?[0-9]+$/" |
||||
|
ng-model='vm.configurations.readRecordsCount' required/> |
||||
|
<div ng-messages="gatewayConfiguration.readRecordsCount.$error"> |
||||
|
<div ng-message="required" translate>gateway.storage-pack-size-required</div> |
||||
|
<div ng-message="min" translate>gateway.storage-pack-size-min</div> |
||||
|
<div ng-message="pattern" translate>gateway.storage-pack-size-pattern</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label translate>{{ vm.configurations.storageType !== 'fileStorage' ? 'gateway.storage-max-records' : 'gateway.storage-max-file-records' }}</label> |
||||
|
<input type="number" min="1" name="maxRecordsCount" ng-pattern="/^-?[0-9]+$/" |
||||
|
ng-model='vm.configurations.maxRecordsCount' required/> |
||||
|
<div ng-messages="gatewayConfiguration.maxRecordsCount.$error"> |
||||
|
<div ng-message="required" translate>gateway.storage-max-records-required</div> |
||||
|
<div ng-message="min" translate>gateway.storage-max-records-min</div> |
||||
|
<div ng-message="pattern" translate>gateway.storage-max-records-pattern</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
|
||||
|
<div layout="row" class="gateway-form-row" |
||||
|
ng-if="vm.configurations.storageType == 'fileStorage'" |
||||
|
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{'gateway.storage-max-files' | translate }}</label> |
||||
|
<input type="number" min="1" name="maxFilesCount" ng-pattern="/^-?[0-9]+$/" |
||||
|
ng-model='vm.configurations.maxFilesCount' required/> |
||||
|
<div ng-messages="gatewayConfiguration.maxFilesCount.$error"> |
||||
|
<div ng-message="required" translate>gateway.storage-max-files-required</div> |
||||
|
<div ng-message="min" translate>gateway.storage-max-files-min</div> |
||||
|
<div ng-message="pattern" translate>gateway.storage-max-files-pattern</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container class="md-block" flex> |
||||
|
<label>{{'gateway.storage-path' | translate }}</label> |
||||
|
<input type="text" name="dataFolderPath" ng-model='vm.configurations.dataFolderPath' |
||||
|
required/> |
||||
|
<div ng-messages="gatewayConfiguration.dataFolderPath.$error"> |
||||
|
<div ng-message="required" translate>gateway.storage-path-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
</md-expansion-panel-content> |
||||
|
</md-expansion-panel-expanded> |
||||
|
</md-expansion-panel> |
||||
|
<md-expansion-panel md-component-id="connectorsPanelId"> |
||||
|
<md-expansion-panel-collapsed> |
||||
|
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
||||
|
<span flex></span> |
||||
|
<md-expansion-panel-icon></md-expansion-panel-icon> |
||||
|
</md-expansion-panel-collapsed> |
||||
|
<md-expansion-panel-expanded> |
||||
|
<md-expansion-panel-header ng-click="vm.collapsePanel('connectorsPanelId')"> |
||||
|
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
||||
|
<span flex></span> |
||||
|
<md-expansion-panel-icon></md-expansion-panel-icon> |
||||
|
</md-expansion-panel-header> |
||||
|
<md-expansion-panel-content> |
||||
|
<tb-gateway-config |
||||
|
gateway-config="vm.configurations.connectors" |
||||
|
the-form="gatewayConfiguration" |
||||
|
change-alignment="vm.changeAlignment"> |
||||
|
</tb-gateway-config> |
||||
|
</md-expansion-panel-content> |
||||
|
</md-expansion-panel-expanded> |
||||
|
</md-expansion-panel> |
||||
|
</md-expansion-panel-group> |
||||
|
<section layout="row" layout-align="end center" class="form-action-buttons"> |
||||
|
<md-button class="md-primary md-raised" |
||||
|
ng-click="vm.exportConfig()" |
||||
|
ng-if="!vm.configurations.remoteConfiguration" |
||||
|
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
||||
|
aria-label="{{ 'gateway.download-tip' | translate }}"> |
||||
|
{{'action.download' | translate }} |
||||
|
<md-tooltip>{{'gateway.download-tip' | translate }}</md-tooltip> |
||||
|
</md-button> |
||||
|
|
||||
|
<md-button class="md-primary md-raised" |
||||
|
ng-click="vm.saveAttributeConfig()" |
||||
|
ng-if="vm.configurations.remoteConfiguration" |
||||
|
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
||||
|
aria-label="{{ 'gateway.save-tip' | translate }}"> |
||||
|
{{'action.save' | translate }} |
||||
|
<md-tooltip ng-if="vm.configurations.remoteConfiguration">{{'gateway.save-tip' | translate }}</md-tooltip> |
||||
|
</md-button> |
||||
|
</section> |
||||
|
</form> |
||||
|
</md-content> |
||||
Loading…
Reference in new issue