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