17 changed files with 1125 additions and 55 deletions
@ -0,0 +1,93 @@ |
|||||
|
# |
||||
|
# Copyright © 2016-2018 The Thingsboard Authors |
||||
|
# |
||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
# you may not use this file except in compliance with the License. |
||||
|
# You may obtain a copy of the License at |
||||
|
# |
||||
|
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
# |
||||
|
# Unless required by applicable law or agreed to in writing, software |
||||
|
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
# See the License for the specific language governing permissions and |
||||
|
# limitations under the License. |
||||
|
# |
||||
|
|
||||
|
--- |
||||
|
apiVersion: v1 |
||||
|
kind: Service |
||||
|
metadata: |
||||
|
labels: |
||||
|
name: redis-service |
||||
|
name: redis-service |
||||
|
spec: |
||||
|
ports: |
||||
|
- name: redis-service |
||||
|
protocol: TCP |
||||
|
port: 6379 |
||||
|
targetPort: 6379 |
||||
|
selector: |
||||
|
app: redis |
||||
|
--- |
||||
|
apiVersion: v1 |
||||
|
kind: ConfigMap |
||||
|
metadata: |
||||
|
name: redis-conf |
||||
|
data: |
||||
|
redis.conf: | |
||||
|
appendonly yes |
||||
|
protected-mode no |
||||
|
bind 0.0.0.0 |
||||
|
port 6379 |
||||
|
dir /var/lib/redis |
||||
|
--- |
||||
|
apiVersion: apps/v1beta1 |
||||
|
kind: StatefulSet |
||||
|
metadata: |
||||
|
name: redis |
||||
|
spec: |
||||
|
serviceName: redis-service |
||||
|
replicas: 1 |
||||
|
template: |
||||
|
metadata: |
||||
|
labels: |
||||
|
app: redis |
||||
|
spec: |
||||
|
terminationGracePeriodSeconds: 10 |
||||
|
containers: |
||||
|
- name: redis |
||||
|
image: redis:4.0.9 |
||||
|
command: |
||||
|
- redis-server |
||||
|
args: |
||||
|
- /etc/redis/redis.conf |
||||
|
resources: |
||||
|
requests: |
||||
|
cpu: 100m |
||||
|
memory: 100Mi |
||||
|
ports: |
||||
|
- containerPort: 6379 |
||||
|
name: redis |
||||
|
volumeMounts: |
||||
|
- name: redis-data |
||||
|
mountPath: /var/lib/redis |
||||
|
- name: redis-conf |
||||
|
mountPath: /etc/redis |
||||
|
volumes: |
||||
|
- name: redis-conf |
||||
|
configMap: |
||||
|
name: redis-conf |
||||
|
items: |
||||
|
- key: redis.conf |
||||
|
path: redis.conf |
||||
|
volumeClaimTemplates: |
||||
|
- metadata: |
||||
|
name: redis-data |
||||
|
annotations: |
||||
|
volume.beta.kubernetes.io/storage-class: fast |
||||
|
spec: |
||||
|
accessModes: [ "ReadWriteOnce" ] |
||||
|
resources: |
||||
|
requests: |
||||
|
storage: 1Gi |
||||
@ -0,0 +1,140 @@ |
|||||
|
/* |
||||
|
* Copyright © 2016-2018 The Thingsboard Authors |
||||
|
* |
||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
* you may not use this file except in compliance with the License. |
||||
|
* You may obtain a copy of the License at |
||||
|
* |
||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
* |
||||
|
* Unless required by applicable law or agreed to in writing, software |
||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
* See the License for the specific language governing permissions and |
||||
|
* limitations under the License. |
||||
|
*/ |
||||
|
import 'brace/ext/language_tools'; |
||||
|
import 'brace/mode/json'; |
||||
|
import 'brace/theme/github'; |
||||
|
|
||||
|
import './extension-form.scss'; |
||||
|
|
||||
|
/* eslint-disable angular/log */ |
||||
|
|
||||
|
import extensionFormModbusTemplate from './extension-form-modbus.tpl.html'; |
||||
|
|
||||
|
/* eslint-enable import/no-unresolved, import/default */ |
||||
|
|
||||
|
/*@ngInject*/ |
||||
|
export default function ExtensionFormModbusDirective($compile, $templateCache, $translate, types) { |
||||
|
|
||||
|
|
||||
|
var linker = function(scope, element) { |
||||
|
|
||||
|
|
||||
|
function Server() { |
||||
|
this.transport = { |
||||
|
"type": "tcp", |
||||
|
"host": "localhost", |
||||
|
"port": 502, |
||||
|
"timeout": 3000 |
||||
|
}; |
||||
|
this.devices = [] |
||||
|
} |
||||
|
|
||||
|
function Device() { |
||||
|
this.unitId = 1; |
||||
|
this.deviceName = ""; |
||||
|
this.attributesPollPeriod = 1000; |
||||
|
this.timeseriesPollPeriod = 1000; |
||||
|
this.attributes = []; |
||||
|
this.timeseries = []; |
||||
|
} |
||||
|
|
||||
|
function Tag(globalPollPeriod) { |
||||
|
this.tag = ""; |
||||
|
this.type = "long"; |
||||
|
this.pollPeriod = globalPollPeriod; |
||||
|
this.functionCode = 3; |
||||
|
this.address = 0; |
||||
|
this.registerCount = 1; |
||||
|
this.bit = 0; |
||||
|
this.byteOrder = "BIG"; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
var template = $templateCache.get(extensionFormModbusTemplate); |
||||
|
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.theForm.$setDirty(); |
||||
|
}; |
||||
|
|
||||
|
scope.addDevice = function(deviceList) { |
||||
|
deviceList.push(new Device()); |
||||
|
scope.theForm.$setDirty(); |
||||
|
}; |
||||
|
|
||||
|
scope.addNewAttribute = function(device) { |
||||
|
device.attributes.push(new Tag(device.attributesPollPeriod)); |
||||
|
scope.theForm.$setDirty(); |
||||
|
}; |
||||
|
|
||||
|
scope.addNewTimeseries = function(device) { |
||||
|
device.timeseries.push(new Tag(device.timeseriesPollPeriod)); |
||||
|
scope.theForm.$setDirty(); |
||||
|
}; |
||||
|
|
||||
|
scope.removeItem = (item, itemList) => { |
||||
|
var index = itemList.indexOf(item); |
||||
|
if (index > -1) { |
||||
|
itemList.splice(index, 1); |
||||
|
} |
||||
|
scope.theForm.$setDirty(); |
||||
|
}; |
||||
|
|
||||
|
scope.onTransportChanged = function(server) { |
||||
|
var type = server.transport.type; |
||||
|
|
||||
|
server.transport = {}; |
||||
|
server.transport.type = type; |
||||
|
server.transport.timeout = 3000; |
||||
|
|
||||
|
scope.theForm.$setDirty(); |
||||
|
}; |
||||
|
|
||||
|
$compile(element.contents())(scope); |
||||
|
|
||||
|
|
||||
|
scope.collapseValidation = function(index, id) { |
||||
|
var invalidState = angular.element('#'+id+':has(.ng-invalid)'); |
||||
|
if(invalidState.length) { |
||||
|
invalidState.addClass('inner-invalid'); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
scope.expandValidation = function (index, id) { |
||||
|
var invalidState = angular.element('#'+id); |
||||
|
invalidState.removeClass('inner-invalid'); |
||||
|
}; |
||||
|
|
||||
|
}; |
||||
|
|
||||
|
return { |
||||
|
restrict: "A", |
||||
|
link: linker, |
||||
|
scope: { |
||||
|
configuration: "=", |
||||
|
isAdd: "=" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,774 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2018 The Thingsboard Authors |
||||
|
|
||||
|
Licensed under the Apache License, Version 2.0 (the "License"); |
||||
|
you may not use this file except in compliance with the License. |
||||
|
You may obtain a copy of the License at |
||||
|
|
||||
|
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
|
||||
|
Unless required by applicable law or agreed to in writing, software |
||||
|
distributed under the License is distributed on an "AS IS" BASIS, |
||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
|
See the License for the specific language governing permissions and |
||||
|
limitations under the License. |
||||
|
|
||||
|
--> |
||||
|
<md-card class="extension-form extension-modbus"> |
||||
|
<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="modbus-server-configs-accordion" class="vAccordion--default" onexpand="expandValidation(index, id)" oncollapse="collapseValidation(index, id)"> |
||||
|
<v-pane id="modbus-servers-pane" expanded="true"> |
||||
|
<v-pane-header> |
||||
|
{{ 'extension.modbus-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.modbus-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 tb-container-for-select"> |
||||
|
<label translate>extension.modbus-transport</label> |
||||
|
<md-select required |
||||
|
name="transportType_{{serverIndex}}" |
||||
|
ng-model="server.transport.type" |
||||
|
ng-change="onTransportChanged(server)" |
||||
|
> |
||||
|
<md-option ng-value="transportType" |
||||
|
ng-repeat="(transportType, transportValue) in types.extensionModbusTransports" |
||||
|
><span ng-bind="transportValue"></span></md-option> |
||||
|
</md-select> |
||||
|
<div ng-messages="theForm['transportType_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<div layout="row" ng-if="server.transport.type == 'tcp' || server.transport.type == 'udp'"> |
||||
|
<md-input-container flex="33" class="md-block"> |
||||
|
<label translate>extension.host</label> |
||||
|
<input required name="transportHost_{{serverIndex}}" ng-model="server.transport.host"> |
||||
|
<div ng-messages="theForm['transportHost_' + serverIndex].$error"> |
||||
|
<div translate ng-message="required">extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="33" class="md-block"> |
||||
|
<label translate>extension.port</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="transportPort_{{serverIndex}}" |
||||
|
ng-model="server.transport.port" |
||||
|
min="1" |
||||
|
max="65535" |
||||
|
> |
||||
|
<div ng-messages="theForm['transportPort_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.port-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.port-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="33" class="md-block"> |
||||
|
<label translate>extension.timeout</label> |
||||
|
<input type="number" |
||||
|
required name="transportTimeout_{{serverIndex}}" |
||||
|
ng-model="server.transport.timeout" |
||||
|
> |
||||
|
<div ng-messages="theForm['transportTimeout_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
|
||||
|
<div ng-if="server.transport.type == 'rtu'"> |
||||
|
|
||||
|
<div layout="row"> |
||||
|
<md-input-container flex="70" class="md-block"> |
||||
|
<label translate>extension.modbus-port-name</label> |
||||
|
<input required name="transportPortName_{{serverIndex}}" ng-model="server.transport.portName"> |
||||
|
<div ng-messages="theForm['transportPortName_' + serverIndex].$error"> |
||||
|
<div translate ng-message="required">extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="30" class="md-block"> |
||||
|
<label translate>extension.timeout</label> |
||||
|
<input type="number" |
||||
|
required name="transportTimeout_{{serverIndex}}" |
||||
|
ng-model="server.transport.timeout" |
||||
|
> |
||||
|
<div ng-messages="theForm['transportTimeout_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.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.modbus-encoding</label> |
||||
|
<md-select required |
||||
|
name="transportEncoding_{{serverIndex}}" |
||||
|
ng-model="server.transport.encoding" |
||||
|
> |
||||
|
<md-option ng-value="encodingType" |
||||
|
ng-repeat="(encodingType, encodingValue) in types.extensionModbusRtuEncodings" |
||||
|
><span ng-bind="encodingValue"></span></md-option> |
||||
|
</md-select> |
||||
|
<div ng-messages="theForm['transportEncoding_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="50" class="md-block tb-container-for-select"> |
||||
|
<label translate>extension.modbus-parity</label> |
||||
|
<md-select name="transportParity_{{serverIndex}}" ng-model="server.transport.parity"> |
||||
|
<md-option ng-repeat="(parityKey, parityValue) in types.extensionModbusRtuParities" |
||||
|
ng-value="parityValue" |
||||
|
> |
||||
|
{{parityValue}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
<div ng-messages="theForm['transportParity_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
<div layout="row"> |
||||
|
<md-input-container flex="33" class="md-block"> |
||||
|
<label translate>extension.modbus-baudrate</label> |
||||
|
<input type="number" |
||||
|
required name="transportBaudRate_{{serverIndex}}" |
||||
|
ng-model="server.transport.baudRate" |
||||
|
> |
||||
|
<div ng-messages="theForm['transportBaudRate_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="33" class="md-block"> |
||||
|
<label translate>extension.modbus-databits</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="transportDataBits_{{serverIndex}}" |
||||
|
ng-model="server.transport.dataBits" |
||||
|
min="7" |
||||
|
max="8" |
||||
|
> |
||||
|
<div ng-messages="theForm['transportDataBits_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-databits-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.modbus-databits-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="33" class="md-block"> |
||||
|
<label translate>extension.modbus-stopbits</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="transportStopBits_{{serverIndex}}" |
||||
|
ng-model="server.transport.stopBits" |
||||
|
min="1" |
||||
|
max="2" |
||||
|
> |
||||
|
<div ng-messages="theForm['transportStopBits_' + serverIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-stopbits-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.modbus-stopbits-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<v-accordion id="modbus-mapping-accordion" |
||||
|
class="vAccordion--default" |
||||
|
onexpand="expandValidation(index, id)" oncollapse="collapseValidation(index, id)"> |
||||
|
<v-pane id="modbus-mapping-pane_{{serverIndex}}"> |
||||
|
<v-pane-header> |
||||
|
{{ 'extension.mapping' | translate }} |
||||
|
</v-pane-header> |
||||
|
<v-pane-content> |
||||
|
<div ng-if="server.devices.length > 0"> |
||||
|
<ol class="list-group"> |
||||
|
<li class="list-group-item" |
||||
|
ng-repeat="(deviceIndex, device) in server.devices" |
||||
|
> |
||||
|
<md-button aria-label="{{ 'action.remove' | translate }}" |
||||
|
class="md-icon-button" |
||||
|
ng-click="removeItem(device, server.devices)" |
||||
|
> |
||||
|
<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="80" class="md-block"> |
||||
|
<label translate>extension.modbus-device-name</label> |
||||
|
<input required |
||||
|
name="deviceName_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="device.deviceName" |
||||
|
> |
||||
|
<div ng-messages="theForm['deviceName_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="20" class="md-block"> |
||||
|
<label translate>extension.modbus-unit-id</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="unitId_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="device.unitId" |
||||
|
min="1" |
||||
|
max="247" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['unitId_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-unit-id-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.modbus-unit-id-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</div> |
||||
|
|
||||
|
<div flex layout="row"> |
||||
|
<md-input-container flex="50" class="md-block"> |
||||
|
<label translate>extension.modbus-attributes-poll-period</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="attributesPollPeriod_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="device.attributesPollPeriod" |
||||
|
min="1" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['attributesPollPeriod_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-poll-period-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="50" class="md-block"> |
||||
|
<label translate>extension.modbus-timeseries-poll-period</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="timeseriesPollPeriod_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="device.timeseriesPollPeriod" |
||||
|
min="1" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['timeseriesPollPeriod_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-poll-period-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<v-accordion id="modbus-attributes-accordion" |
||||
|
class="vAccordion--default" |
||||
|
onexpand="expandValidation(index, id)" oncollapse="collapseValidation(index, id)"> |
||||
|
<v-pane id="modbus-attributes-pane_{{serverIndex}}{{deviceIndex}}"> |
||||
|
<v-pane-header> |
||||
|
{{ 'extension.attributes' | translate }} |
||||
|
</v-pane-header> |
||||
|
<v-pane-content> |
||||
|
<div ng-show="device.attributes.length > 0"> |
||||
|
<ol class="list-group"> |
||||
|
<li class="list-group-item" |
||||
|
ng-repeat="(attributeIndex, attribute) in device.attributes" |
||||
|
> |
||||
|
<md-button aria-label="{{ 'action.remove' | translate }}" |
||||
|
class="md-icon-button" |
||||
|
ng-click="removeItem(attribute, device.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="50" class="md-block"> |
||||
|
<label translate>extension.modbus-tag</label> |
||||
|
<input required |
||||
|
name="modbusAttributeTag_{{serverIndex}}{{deviceIndex}}{{attributeIndex}}" |
||||
|
ng-model="attribute.tag" |
||||
|
> |
||||
|
<div ng-messages="theForm['modbusAttributeTag_' + serverIndex + deviceIndex + attributeIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="30" class="md-block tb-container-for-select"> |
||||
|
<label translate>extension.type</label> |
||||
|
<md-select required name="modbusAttributeType_{{serverIndex}}{{deviceIndex}}{{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['modbusAttributeType_' + serverIndex + deviceIndex + attributeIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="20" class="md-block"> |
||||
|
<label translate>extension.modbus-poll-period</label> |
||||
|
<input type="number" |
||||
|
name="pollPeriod_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="attribute.pollPeriod" |
||||
|
min="1" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['pollPeriod_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-poll-period-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</section> |
||||
|
|
||||
|
<section flex layout="row"> |
||||
|
<md-input-container flex="50" class="md-block tb-container-for-select"> |
||||
|
<label translate>extension.type</label> |
||||
|
<md-select required name="modbusAttributeFunctionCode_{{serverIndex}}{{deviceIndex}}{{attributeIndex}}" |
||||
|
ng-model="attribute.functionCode" |
||||
|
> |
||||
|
<md-option ng-repeat="(functionCode, functionName) in types.extensionModbusFunctionCodes" |
||||
|
ng-value="functionCode" |
||||
|
> |
||||
|
{{functionName}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
<div ng-messages="theForm['modbusAttributeFunctionCode_' + serverIndex + deviceIndex + attributeIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="50" class="md-block"> |
||||
|
<label translate>extension.modbus-register-address</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="address_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="attribute.address" |
||||
|
min="0" |
||||
|
max="65535" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['address_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-register-address-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.modbus-register-address-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
</section> |
||||
|
|
||||
|
<section flex layout="row"> |
||||
|
<md-input-container flex="50" class="md-block" ng-if="attribute.type != 'boolean'"> |
||||
|
<label translate>extension.modbus-register-count</label> |
||||
|
<input type="number" |
||||
|
name="registerCount_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="attribute.registerCount" |
||||
|
min="1" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['registerCount_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-register-count-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="50" class="md-block" ng-if="attribute.type == 'boolean' && attribute.functionCode >= 3"> |
||||
|
<label translate>extension.modbus-register-bit-index</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="bit_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="attribute.bit" |
||||
|
min="0" |
||||
|
max="15" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['bit_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-register-bit-index-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.modbus-register-bit-index-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</section> |
||||
|
|
||||
|
<section flex layout="row"> |
||||
|
<md-input-container flex="100" class="md-block" ng-if="attribute.functionCode >= 3"> |
||||
|
<label translate>extension.modbus-byte-order</label> |
||||
|
<input required |
||||
|
name="modbusByteOrder_{{serverIndex}}{{deviceIndex}}{{attributeIndex}}" |
||||
|
ng-model="attribute.byteOrder" |
||||
|
> |
||||
|
<div ng-messages="theForm['modbusByteOrder_' + serverIndex + deviceIndex + attributeIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.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(device)" |
||||
|
aria-label="{{ 'action.add' | translate }}" |
||||
|
> |
||||
|
<md-icon class="material-icons">add</md-icon> |
||||
|
<span translate>extension.add-attribute</span> |
||||
|
</md-button> |
||||
|
</div> |
||||
|
</v-pane-content> |
||||
|
</v-pane> |
||||
|
</v-accordion> |
||||
|
|
||||
|
<v-accordion id="modbus-timeseries-accordion" class="vAccordion--default" onexpand="expandValidation(index, id)" oncollapse="collapseValidation(index, id)"> |
||||
|
<v-pane id="modbus-timeseries-pane_{{serverIndex}}{{deviceIndex}}"> |
||||
|
<v-pane-header> |
||||
|
{{ 'extension.timeseries' | translate }} |
||||
|
</v-pane-header> |
||||
|
<v-pane-content> |
||||
|
<div ng-show="device.timeseries.length > 0"> |
||||
|
<ol class="list-group"> |
||||
|
<li class="list-group-item" |
||||
|
ng-repeat="(timeseriesIndex, timeserie) in device.timeseries" |
||||
|
> |
||||
|
<md-button aria-label="{{ 'action.remove' | translate }}" |
||||
|
class="md-icon-button" |
||||
|
ng-click="removeItem(timeserie, device.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="50" class="md-block"> |
||||
|
<label translate>extension.modbus-tag</label> |
||||
|
<input required |
||||
|
name="modbusTimeserieTag_{{serverIndex}}{{deviceIndex}}{{timeseriesIndex}}" |
||||
|
ng-model="timeserie.tag" |
||||
|
> |
||||
|
<div ng-messages="theForm['modbusTimeserieTag_' + serverIndex + deviceIndex + timeseriesIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="30" class="md-block tb-container-for-select"> |
||||
|
<label translate>extension.type</label> |
||||
|
<md-select required name="modbusTimeserieType_{{serverIndex}}{{deviceIndex}}{{timeseriesIndex}}" |
||||
|
ng-model="timeserie.type" |
||||
|
> |
||||
|
<md-option ng-repeat="(attrType, attrTypeValue) in types.extensionValueType" |
||||
|
ng-value="attrType" |
||||
|
> |
||||
|
{{attrTypeValue | translate}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
<div ng-messages="theForm['modbusTimeserieType_' + serverIndex + deviceIndex + timeseriesIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="20" class="md-block"> |
||||
|
<label translate>extension.modbus-poll-period</label> |
||||
|
<input type="number" |
||||
|
name="pollPeriod_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="timeserie.pollPeriod" |
||||
|
min="1" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['pollPeriod_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-poll-period-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</section> |
||||
|
|
||||
|
<section flex layout="row"> |
||||
|
<md-input-container flex="50" class="md-block tb-container-for-select"> |
||||
|
<label translate>extension.type</label> |
||||
|
<md-select required name="modbusTimeserieFunctionCode_{{serverIndex}}{{deviceIndex}}{{timeseriesIndex}}" |
||||
|
ng-model="timeserie.functionCode" |
||||
|
> |
||||
|
<md-option ng-repeat="(functionCode, functionName) in types.extensionModbusFunctionCodes" |
||||
|
ng-value="functionCode" |
||||
|
> |
||||
|
{{functionName}} |
||||
|
</md-option> |
||||
|
</md-select> |
||||
|
<div ng-messages="theForm['modbusTimeserieFunctionCode_' + serverIndex + deviceIndex + timeseriesIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="50" class="md-block"> |
||||
|
<label translate>extension.modbus-register-address</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="address_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="timeserie.address" |
||||
|
min="0" |
||||
|
max="65535" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['address_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-register-address-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.modbus-register-address-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</section> |
||||
|
|
||||
|
<section flex layout="row"> |
||||
|
<md-input-container flex="50" class="md-block" ng-if="timeserie.type != 'boolean'"> |
||||
|
<label translate>extension.modbus-register-count</label> |
||||
|
<input type="number" |
||||
|
name="registerCount_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="timeserie.registerCount" |
||||
|
min="1" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['registerCount_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-register-count-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
|
||||
|
<md-input-container flex="50" class="md-block" ng-if="timeserie.type == 'boolean' && timeserie.functionCode >= 3"> |
||||
|
<label translate>extension.modbus-register-bit-index</label> |
||||
|
<input type="number" |
||||
|
required |
||||
|
name="bit_{{serverIndex}}{{deviceIndex}}" |
||||
|
ng-model="timeserie.bit" |
||||
|
min="0" |
||||
|
max="15" |
||||
|
> |
||||
|
|
||||
|
<div ng-messages="theForm['bit_' + serverIndex + deviceIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.field-required</div> |
||||
|
<div translate |
||||
|
ng-message="min" |
||||
|
>extension.modbus-register-bit-index-range</div> |
||||
|
<div translate |
||||
|
ng-message="max" |
||||
|
>extension.modbus-register-bit-index-range</div> |
||||
|
</div> |
||||
|
</md-input-container> |
||||
|
</section> |
||||
|
|
||||
|
<section flex layout="row"> |
||||
|
<md-input-container flex="100" class="md-block" ng-if="timeserie.functionCode >= 3"> |
||||
|
<label translate>extension.modbus-byte-order</label> |
||||
|
<input required |
||||
|
name="modbusByteOrder_{{serverIndex}}{{deviceIndex}}{{timeseriesIndex}}" |
||||
|
ng-model="timeserie.byteOrder" |
||||
|
> |
||||
|
<div ng-messages="theForm['modbusByteOrder_' + serverIndex + deviceIndex + timeseriesIndex].$error"> |
||||
|
<div translate |
||||
|
ng-message="required" |
||||
|
>extension.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="addNewTimeseries(device)" |
||||
|
aria-label="{{ 'action.add' | translate }}" |
||||
|
> |
||||
|
<md-icon class="material-icons">add</md-icon> |
||||
|
<span translate>extension.add-timeseries</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="addDevice(server.devices)" |
||||
|
aria-label="{{ 'action.add' | translate }}" |
||||
|
> |
||||
|
<md-icon class="material-icons">add</md-icon> |
||||
|
<span translate>extension.add-device</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.modbus-add-server</span> |
||||
|
</md-button> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</v-pane-content> |
||||
|
</v-pane> |
||||
|
</v-accordion> |
||||
|
<!--{{config}}--> |
||||
|
</md-card-content> |
||||
|
</md-card> |
||||
Loading…
Reference in new issue