diff --git a/ui/src/app/common/types.constant.js b/ui/src/app/common/types.constant.js index ef6ffde28a..66ed196854 100644 --- a/ui/src/app/common/types.constant.js +++ b/ui/src/app/common/types.constant.js @@ -384,7 +384,8 @@ export default angular.module('thingsboard.types', []) extensionType: { http: "HTTP", mqtt: "MQTT", - opc: "OPC UA" + opc: "OPC UA", + modbus: "MODBUS" }, extensionValueType: { string: 'value.string', @@ -428,6 +429,26 @@ export default angular.module('thingsboard.types', []) PKCS12: "PKCS12", JKS: "JKS" }, + extensionModbusFunctionCodes: { + 1: "Read Coils (1)", + 2: "Read Discrete Inputs (2)", + 3: "Read Multiple Holding Registers (3)", + 4: "Read Input Registers (4)" + }, + extensionModbusTransports: { + tcp: "TCP", + udp: "UDP", + rtu: "RTU" + }, + extensionModbusRtuParities: { + none: "none", + even: "even", + odd: "odd" + }, + extensionModbusRtuEncodings: { + ascii: "ascii", + rtu: "rtu" + }, latestTelemetry: { value: "LATEST_TELEMETRY", name: "attribute.scope-latest-telemetry", diff --git a/ui/src/app/extension/extension-dialog.controller.js b/ui/src/app/extension/extension-dialog.controller.js index 2b0eded0ae..4b8221a4a2 100644 --- a/ui/src/app/extension/extension-dialog.controller.js +++ b/ui/src/app/extension/extension-dialog.controller.js @@ -49,7 +49,7 @@ export default function ExtensionDialogController($scope, $mdDialog, $translate, "brokers": [] }; } - if (vm.extension.type === "OPC UA") { + if (vm.extension.type === "OPC UA" || vm.extension.type === "MODBUS") { vm.extension.configuration = { "servers": [] }; diff --git a/ui/src/app/extension/extension-dialog.tpl.html b/ui/src/app/extension/extension-dialog.tpl.html index 4e200d5bad..fcf78407e6 100644 --- a/ui/src/app/extension/extension-dialog.tpl.html +++ b/ui/src/app/extension/extension-dialog.tpl.html @@ -62,6 +62,7 @@
+
diff --git a/ui/src/app/extension/extensions-forms/extension-form-modbus.directive.js b/ui/src/app/extension/extensions-forms/extension-form-modbus.directive.js new file mode 100644 index 0000000000..aec5625eb7 --- /dev/null +++ b/ui/src/app/extension/extensions-forms/extension-form-modbus.directive.js @@ -0,0 +1,131 @@ +/* + * 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(); + }; + + + $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: "=" + } + } +} \ No newline at end of file diff --git a/ui/src/app/extension/extensions-forms/extension-form-modbus.tpl.html b/ui/src/app/extension/extensions-forms/extension-form-modbus.tpl.html new file mode 100644 index 0000000000..122aeaf23e --- /dev/null +++ b/ui/src/app/extension/extensions-forms/extension-form-modbus.tpl.html @@ -0,0 +1,818 @@ + + + + + extension.configuration + + + + + + + + {{ 'extension.modbus-server' | translate }} + + + +
+ extension.modbus-add-server-prompt +
+ +
+
    +
  1. + + + + {{ 'action.remove' | translate }} + + + + + + +
    + + + + + + +
    +
    extension.field-required
    +
    +
    + +
    + +
    + + + +
    +
    extension.field-required
    +
    +
    + + + + +
    +
    extension.field-required
    +
    extension.port-range
    +
    extension.port-range
    +
    +
    + + + + +
    +
    extension.field-required
    +
    +
    +
    + +
    + + + +
    +
    extension.field-required
    +
    +
    + + + + +
    +
    extension.field-required
    +
    extension.port-range
    +
    extension.port-range
    +
    +
    + + + + +
    +
    extension.field-required
    +
    +
    +
    + +
    + +
    + + + +
    +
    extension.field-required
    +
    +
    + + + + +
    +
    extension.field-required
    +
    +
    +
    + +
    + + + + + +
    +
    extension.field-required
    +
    +
    + + + + + + {{parityValue}} + + +
    +
    extension.field-required
    +
    +
    + +
    + +
    + + + +
    +
    extension.field-required
    +
    +
    + + + + +
    +
    extension.field-required
    +
    extension.modbus-databits-range
    +
    extension.modbus-databits-range
    +
    +
    + + + + +
    +
    extension.field-required
    +
    extension.modbus-stopbits-range
    +
    extension.modbus-stopbits-range
    +
    +
    +
    +
    + + + + + {{ 'extension.mapping' | translate }} + + +
    +
      +
    1. + + + + {{ 'action.remove' | translate }} + + + + + +
      + + + +
      +
      extension.field-required
      +
      +
      + + + + + +
      +
      extension.field-required
      +
      extension.modbus-unit-id-range
      +
      extension.modbus-unit-id-range
      +
      +
      +
      + +
      + + + + +
      +
      extension.field-required
      +
      extension.modbus-poll-period-range
      +
      +
      + + + + + +
      +
      extension.field-required
      +
      extension.modbus-poll-period-range
      +
      +
      + +
      + + + + + + {{ 'extension.attributes' | translate }} + + +
      +
        +
      1. + + + + {{ 'action.remove' | translate }} + + + + + +
        + + + +
        +
        extension.field-required
        +
        +
        + + + + + + {{attrTypeValue | translate}} + + +
        +
        extension.field-required
        +
        +
        + + + + + +
        +
        extension.modbus-poll-period-range
        +
        +
        +
        + +
        + + + + + {{functionName}} + + +
        +
        extension.field-required
        +
        +
        + + + + + +
        +
        extension.field-required
        +
        extension.modbus-register-address-range
        +
        extension.modbus-register-address-range
        +
        +
        + +
        + +
        + + + + +
        +
        extension.modbus-register-count-range
        +
        +
        + + + + + +
        +
        extension.field-required
        +
        extension.modbus-register-bit-index-range
        +
        extension.modbus-register-bit-index-range
        +
        +
        +
        + +
        + + + +
        +
        extension.field-required
        +
        +
        + +
        + + +
        +
        +
      2. +
      +
      +
      + + add + extension.add-attribute + +
      +
      +
      +
      + + + + + {{ 'extension.timeseries' | translate }} + + +
      +
        +
      1. + + + + {{ 'action.remove' | translate }} + + + + + +
        + + + +
        +
        extension.field-required
        +
        +
        + + + + + + {{attrTypeValue | translate}} + + +
        +
        extension.field-required
        +
        +
        + + + + + +
        +
        extension.modbus-poll-period-range
        +
        +
        +
        + +
        + + + + + {{functionName}} + + +
        +
        extension.field-required
        +
        +
        + + + + + +
        +
        extension.field-required
        +
        extension.modbus-register-address-range
        +
        extension.modbus-register-address-range
        +
        +
        +
        + +
        + + + + +
        +
        extension.modbus-register-count-range
        +
        +
        + + + + + +
        +
        extension.field-required
        +
        extension.modbus-register-bit-index-range
        +
        extension.modbus-register-bit-index-range
        +
        +
        +
        + +
        + + + +
        +
        extension.field-required
        +
        +
        + +
        +
        +
        +
      2. +
      +
      +
      + + add + extension.add-timeseries + +
      +
      +
      +
      + + +
      +
      +
    2. +
    +
    +
    + + add + extension.add-device + +
    +
    +
    +
    + +
    +
    +
  2. +
+ +
+ + add + extension.modbus-add-server + +
+ +
+
+
+
+ +
+
\ No newline at end of file diff --git a/ui/src/app/extension/index.js b/ui/src/app/extension/index.js index f04880cb97..8e293482f4 100644 --- a/ui/src/app/extension/index.js +++ b/ui/src/app/extension/index.js @@ -17,6 +17,8 @@ import ExtensionTableDirective from './extension-table.directive'; import ExtensionFormHttpDirective from './extensions-forms/extension-form-http.directive'; import ExtensionFormMqttDirective from './extensions-forms/extension-form-mqtt.directive' import ExtensionFormOpcDirective from './extensions-forms/extension-form-opc.directive'; +import ExtensionFormModbusDirective from './extensions-forms/extension-form-modbus.directive'; + import {ParseToNull} from './extension-dialog.controller'; export default angular.module('thingsboard.extension', []) @@ -24,5 +26,6 @@ export default angular.module('thingsboard.extension', []) .directive('tbExtensionFormHttp', ExtensionFormHttpDirective) .directive('tbExtensionFormMqtt', ExtensionFormMqttDirective) .directive('tbExtensionFormOpc', ExtensionFormOpcDirective) + .directive('tbExtensionFormModbus', ExtensionFormModbusDirective) .directive('parseToNull', ParseToNull) .name; \ No newline at end of file diff --git a/ui/src/app/locale/locale.constant.js b/ui/src/app/locale/locale.constant.js index 252884dfc7..0f0a1dfd3a 100644 --- a/ui/src/app/locale/locale.constant.js +++ b/ui/src/app/locale/locale.constant.js @@ -866,8 +866,10 @@ export default angular.module('thingsboard.locale', []) "response-timeout": "Response timeout in milliseconds", "topic-expression": "Topic expression", "client-scope": "Client scope", + "add-device": "Add device", "opc-server": "Servers", "opc-add-server": "Add server", + "opc-add-server-prompt": "Please add server", "opc-application-name": "Application name", "opc-application-uri": "Application uri", "opc-scan-period-in-seconds": "Scan period in seconds", @@ -882,6 +884,34 @@ export default angular.module('thingsboard.locale', []) "opc-keystore-key-password":"Key password", "opc-device-node-pattern":"Device node pattern", "opc-device-name-pattern":"Device name pattern", + "modbus-server": "Servers/slaves", + "modbus-add-server": "Add server/slave", + "modbus-add-server-prompt": "Please add server/slave", + "modbus-transport": "Transport", + "modbus-port-name": "Serial port name", + "modbus-encoding": "Encoding", + "modbus-parity": "Parity", + "modbus-baudrate": "Baud rate", + "modbus-databits": "Data bits", + "modbus-stopbits": "Stop bits", + "modbus-databits-range": "Data bits should be in a range from 7 to 8.", + "modbus-stopbits-range": "Stop bits should be in a range from 1 to 2.", + "modbus-unit-id": "Unit ID", + "modbus-unit-id-range": "Unit ID should be in a range from 1 to 247.", + "modbus-device-name":"Device name", + "modbus-poll-period": "Poll period (ms)", + "modbus-attributes-poll-period": "Attributes poll period (ms)", + "modbus-timeseries-poll-period": "Timeseries poll period (ms)", + "modbus-poll-period-range": "Poll period should be positive value.", + "modbus-tag": "Tag", + "modbus-function": "Function", + "modbus-register-address": "Register address", + "modbus-register-address-range": "Register address should be in a range from 0 to 65535.", + "modbus-register-bit-index": "Bit index", + "modbus-register-bit-index-range": "Bit index should be in a range from 0 to 15.", + "modbus-register-count": "Register count", + "modbus-register-count-range": "Register count should be a positive value.", + "modbus-byte-order": "Byte order", "sync": { "status": "Status",