Browse Source

functionality adjustments

pull/11235/head
mpetrov 2 years ago
parent
commit
62e2c8a6ad
  1. 9
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html
  2. 25
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts
  3. 3
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.html
  4. 15
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.ts
  5. 10
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html
  6. 64
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts
  7. 9
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html
  8. 4
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts
  9. 2
      ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts
  10. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

9
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html

@ -27,7 +27,10 @@
<mat-expansion-panel-header fxLayout="row wrap">
<mat-panel-title>
<div class="title-container">
{{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }}
<span *ngIf="isMaster else tagName">
{{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }}
</span>
<ng-template #tagName>{{ keyControl.get('tag').value }}</ng-template>
</div>
</mat-panel-title>
</mat-expansion-panel-header>
@ -73,7 +76,7 @@
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="functionCode">
<mat-option *ngFor="let code of functionCodesMap.get(keyControl.get('tag').value + keyControl.get('address').value) || defaultFunctionCodes" [value]="code">{{ ModbusFunctionCodeTranslationsMap.get(code) | translate }}</mat-option>
<mat-option *ngFor="let code of functionCodesMap.get(keyControl.get('id').value) || defaultFunctionCodes" [value]="code">{{ ModbusFunctionCodeTranslationsMap.get(code) | translate }}</mat-option>
</mat-select>
</mat-form-field>
</div>
@ -102,7 +105,7 @@
</mat-form-field>
</div>
</div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div *ngIf="isMaster" class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width tb-required" translate>gateway.value</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">

25
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts

@ -18,7 +18,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { AbstractControl, FormGroup, UntypedFormArray, UntypedFormBuilder, Validators } from '@angular/forms';
import { TbPopoverComponent } from '@shared/components/popover.component';
import {
MappingKeysType,
ModbusDataType,
ModbusFunctionCodeTranslationsMap,
ModbusObjectCountByDataType,
@ -30,6 +29,7 @@ import {
import { CommonModule } from '@angular/common';
import { SharedModule } from '@shared/shared.module';
import { GatewayHelpLinkPipe } from '@home/pipes/public-api';
import { generateSecret } from '@core/utils';
@Component({
selector: 'tb-modbus-data-keys-panel',
@ -83,11 +83,12 @@ export class ModbusDataKeysPanelComponent implements OnInit {
addKey(): void {
const dataKeyFormGroup = this.fb.group({
tag: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
value: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
value: [{value: '', disabled: !this.isMaster}, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
type: [ModbusDataType.STRING, [Validators.required]],
address: [0, [Validators.required]],
objectsCount: [1, [Validators.required]],
functionCode: [this.getDefaultFunctionCodes()[0]]
functionCode: [this.getDefaultFunctionCodes()[0]],
id: [{value: generateSecret(5), disabled: true}],
});
this.observeKeyDataType(dataKeyFormGroup);
@ -117,14 +118,15 @@ export class ModbusDataKeysPanelComponent implements OnInit {
const { tag, value, type, address, objectsCount, functionCode } = keyData;
const dataKeyFormGroup = this.fb.group({
tag: [tag, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
value: [value, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
value: [{value, disabled: !this.isMaster}, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
type: [type, [Validators.required]],
address: [address, [Validators.required]],
objectsCount: [objectsCount, [Validators.required]],
functionCode: [functionCode, []],
id: [{value: generateSecret(5), disabled: true}],
});
this.observeKeyDataType(dataKeyFormGroup);
this.functionCodesMap.set(tag+address, this.getFunctionCodes(type));
this.functionCodesMap.set(dataKeyFormGroup.get('id').value, this.getFunctionCodes(type));
keysControlGroups.push(dataKeyFormGroup);
});
@ -138,8 +140,7 @@ export class ModbusDataKeysPanelComponent implements OnInit {
if (!this.editableDataTypes.includes(dataType)) {
objectsCountControl.patchValue(ModbusObjectCountByDataType[dataType]);
}
const keyId = keyFormGroup.get('tag').value + keyFormGroup.get('address').value;
this.functionCodesMap.set(keyId, this.getFunctionCodes(dataType));
this.functionCodesMap.set(keyFormGroup.get('id').value, this.getFunctionCodes(dataType));
});
}
@ -147,7 +148,7 @@ export class ModbusDataKeysPanelComponent implements OnInit {
if (this.keysType === ModbusValueKey.ATTRIBUTES_UPDATES) {
return this.defaultWriteFunctionCodes;
}
const functionCodes = this.defaultReadFunctionCodes;
const functionCodes = [...this.defaultReadFunctionCodes];
if (dataType === ModbusDataType.BITS) {
const bitsFunctionCodes = [1, 2];
bitsFunctionCodes.forEach(code => functionCodes.push(code));
@ -160,6 +161,12 @@ export class ModbusDataKeysPanelComponent implements OnInit {
}
private getDefaultFunctionCodes(): number[] {
return this.keysType === ModbusValueKey.ATTRIBUTES_UPDATES ? this.defaultWriteFunctionCodes : this.defaultReadFunctionCodes;
if (this.keysType === ModbusValueKey.ATTRIBUTES_UPDATES) {
return this.defaultWriteFunctionCodes;
}
if (this.keysType === ModbusValueKey.RPC_REQUESTS) {
return [...this.defaultReadFunctionCodes, ...this.defaultWriteFunctionCodes];
}
return this.defaultReadFunctionCodes;
}
}

3
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.html

@ -15,7 +15,8 @@
limitations under the License.
-->
<div class="tb-form-panel no-border no-padding padding-top" [formGroup]="securityConfigFormGroup">
<div class="tb-form-panel no-border no-padding" [formGroup]="securityConfigFormGroup">
<div class="tb-form-hint tb-primary-fill">{{ 'gateway.hints.path-in-os' | translate }}</div>
<div class="tb-form-row space-between tb-flex fill-width">
<div class="fixed-title-width" translate>gateway.client-cert-path</div>
<div class="tb-flex no-gap">

15
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component.ts

@ -112,7 +112,20 @@ export class ModbusSecurityConfigComponent implements ControlValueAccessor, Vali
}
writeValue(securityConfig: ModbusSecurity): void {
this.securityConfigFormGroup.patchValue(securityConfig, {emitEvent: false});
const { certfile, password, keyfile, server_hostname } = securityConfig;
let securityState = {
certfile: certfile ?? '',
password: password ?? '',
keyfile: keyfile ?? '',
server_hostname: server_hostname?? '',
reqclicert: !!securityConfig.reqclicert,
};
if (this.isMaster) {
securityState = { ...securityState, reqclicert: !!securityConfig.reqclicert };
} else {
securityState = { ...securityState, server_hostname: server_hostname ?? '' };
}
this.securityConfigFormGroup.reset(securityState, {emitEvent: false});
}
private observeValueChanges(): void {

10
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html

@ -16,6 +16,7 @@
-->
<div class="tb-form-panel no-border no-padding padding-top" [formGroup]="slaveConfigFormGroup">
<div class="tb-form-hint tb-primary-fill tb-flex center">{{ 'gateway.hints.modbus-server' | translate }}</div>
<div class="tb-flex row space-between align-center no-gap fill-width">
<div class="fixed-title-width" translate>gateway.server-slave-config</div>
<tb-toggle-select formControlName="type" appearance="fill">
@ -105,6 +106,15 @@
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" min="0" name="value" formControlName="unitId" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="('gateway.unit-id-required') | translate"
*ngIf="slaveConfigFormGroup.get('unitId').hasError('required') &&
slaveConfigFormGroup.get('unitId').touched"
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
</div>

64
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts

@ -23,7 +23,8 @@ import {
UntypedFormControl,
UntypedFormGroup,
ValidationErrors,
Validator, Validators,
Validator,
Validators,
} from '@angular/forms';
import {
ModbusMethodLabelsMap,
@ -31,8 +32,11 @@ import {
ModbusOrderType,
ModbusProtocolLabelsMap,
ModbusProtocolType,
ModbusRegisterValues,
ModbusSlave,
noLeadTrailSpacesRegex,
PortLimits, SlaveConfig,
PortLimits,
SlaveConfig,
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { SharedModule } from '@shared/shared.module';
import { CommonModule } from '@angular/common';
@ -104,7 +108,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat
port: [null, [Validators.required, Validators.min(PortLimits.MIN), Validators.max(PortLimits.MAX)]],
serialPort: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
method: [ModbusMethodType.SOCKET, []],
unitId: [null, []],
unitId: [null, [Validators.required]],
baudrate: [null, []],
deviceName: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
deviceType: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
@ -155,13 +159,9 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat
};
}
writeValue(slaveConfig: SlaveConfig): void {
if (slaveConfig.type === ModbusProtocolType.Serial) {
slaveConfig.serialPort = slaveConfig.port as string;
delete slaveConfig.port;
}
this.slaveConfigFormGroup.patchValue(slaveConfig, {emitEvent: false});
writeValue(slaveConfig: ModbusSlave): void {
this.showSecurityControl.patchValue(!!slaveConfig.security);
this.updateSlaveConfig(slaveConfig);
this.updateControlsEnabling(slaveConfig.type);
}
@ -180,4 +180,50 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat
this.tcpUdpSpecificControlKeys.forEach(key => this.slaveConfigFormGroup.get(key)?.enable({emitEvent: false}));
}
};
private updateSlaveConfig(slaveConfig: ModbusSlave): void {
const {
type,
method,
unitId,
deviceName,
deviceType,
pollPeriod,
sendDataToThingsBoard,
byteOrder,
security,
identity,
values,
baudrate,
host,
port,
} = slaveConfig;
let slaveState: ModbusSlave = {
host: host ?? '',
type: type ?? ModbusProtocolType.TCP,
method: method ?? ModbusMethodType.SOCKET,
unitId: unitId ?? null,
deviceName: deviceName ?? '',
deviceType: deviceType ?? '',
pollPeriod: pollPeriod ?? null,
sendDataToThingsBoard: !!sendDataToThingsBoard,
byteOrder: byteOrder ?? ModbusOrderType.BIG,
security: security ?? {},
identity: identity ?? {
vendorName: '',
productCode: '',
vendorUrl: '',
productName: '',
modelName: '',
},
values: values ?? {} as ModbusRegisterValues,
port: port ?? null,
};
if (slaveConfig.type === ModbusProtocolType.Serial) {
slaveState = { ...slaveState, baudrate, serialPort: port, host: '', port: null } as ModbusSlave;
} else {
slaveState = { ...slaveState, serialPort: '', baudrate: null } as ModbusSlave;
}
this.slaveConfigFormGroup.setValue(slaveState, {emitEvent: false});
}
}

9
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html

@ -176,6 +176,15 @@
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<input matInput type="number" min="0" name="value" formControlName="unitId" placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="('gateway.unit-id-required') | translate"
*ngIf="slaveConfigFormGroup.get('unitId').hasError('required') &&
slaveConfigFormGroup.get('unitId').touched"
class="tb-error">
warning
</mat-icon>
</mat-form-field>
</div>
</div>

4
ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts

@ -125,7 +125,7 @@ export class ModbusSlaveDialogComponent extends DialogComponent<ModbusSlaveDialo
bytesize: [null, []],
parity: [null, []],
strict: [false, []],
unitId: [null, []],
unitId: [null, [Validators.required]],
deviceName: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
deviceType: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]],
sendDataOnlyOnChange: [false, []],
@ -140,7 +140,7 @@ export class ModbusSlaveDialogComponent extends DialogComponent<ModbusSlaveDialo
connectAttemptCount: [null, []],
waitAfterFailedAttemptsMs: [null, []],
values: [{}, []],
security: [],
security: [{}],
});
this.slaveConfigFormGroup.patchValue({

2
ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts

@ -957,6 +957,7 @@ export interface ModbusSecurity {
keyfile?: string;
password?: string;
server_hostname?: string;
reqclicert?: boolean;
}
export interface ModbusSlave {
@ -964,6 +965,7 @@ export interface ModbusSlave {
type: ModbusProtocolType;
method: ModbusMethodType;
unitId: number;
serialPort?: string;
baudrate?: number;
deviceName: string;
deviceType: string;

3
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -3313,6 +3313,7 @@
"update-config": "Add/update configuration JSON",
"username": "Username",
"username-required": "Username is required.",
"unit-id-required": "Unit ID is required.",
"read-coils": "Read Coils",
"read-discrete-inputs": "Read Discrete Inputs",
"read-multiple-holding-registers": "Read Multiple Holding Register",
@ -3322,6 +3323,7 @@
"write-register": "Write Register",
"write-registers": "Write Registers",
"hints": {
"modbus-server": "Starting with version 3.0, Gateway can run as a Modbus slave.",
"remote-configuration": "Enables remote configuration and management of the gateway",
"remote-shell": "Enables remote control of the operating system with the gateway from the Remote Shell widget",
"host": "Hostname or IP address of platform server",
@ -3360,6 +3362,7 @@
"grpc-max-pings-without-data": "Maximum number of keepalive ping messages that the server can send without receiving any data before it considers the connection dead.",
"grpc-min-ping-interval-without-data": "Minimum amount of time the server should wait between sending keepalive ping messages when there is no data being sent or received.",
"permit-without-calls": "Allow server to keep the GRPC connection alive even when there are no active RPC calls.",
"path-in-os": "Path in gateway os.",
"memory": "Your data will be stored in the in-memory queue, it is a fastest but no persistence guarantee.",
"framer-type": "Type of framer.",
"file": "Your data will be stored in separated files and will be saved even after the gateway restart.",

Loading…
Cancel
Save