From 2ae1f3158e36b6850e7ad3144adaf805729a2f6f Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 26 Jul 2024 18:41:48 +0300 Subject: [PATCH 01/29] Removed Unexpected Tooltips from toolbar on Edit Connectors Tables --- .../mapping-table/mapping-table.component.html | 2 +- .../modbus-master-table/modbus-master-table.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html index 9f0566b566..39cc1162c0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html @@ -18,7 +18,7 @@
-
+
{{mappingTypeTranslationsMap.get(mappingType) | translate}}
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html index e16aa0c51f..7dd4e29795 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html @@ -18,7 +18,7 @@
-
+
{{ 'gateway.servers-slaves' | translate}}
From 8119e26369fccaaea96e0a224209e14cffc73746 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 26 Jul 2024 19:10:08 +0300 Subject: [PATCH 02/29] Added Connector tables Row Action buttons descriptions tooltips --- .../mapping-table.component.html | 18 +++++------ .../modbus-master-table.component.html | 32 +++++++++---------- .../modbus-master-table.component.ts | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html index 9f0566b566..76e7294403 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component.html @@ -75,15 +75,22 @@ -
+ + +
+
- - +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html index e16aa0c51f..29e2fb6ccf 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html @@ -63,33 +63,40 @@ {{ 'gateway.name' | translate }} - - {{ mapping['name'] }} + + {{ slave['name'] }} {{ 'gateway.client-communication-type' | translate }} - - {{ ModbusProtocolLabelsMap.get(mapping['type']) }} + + {{ ModbusProtocolLabelsMap.get(slave['type']) }} - -
+ + +
+
- - +
- +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 2cb66f6062..915de21c32 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -185,7 +185,7 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat }); } - deleteMapping($event: Event, index: number): void { + deleteSlave($event: Event, index: number): void { if ($event) { $event.stopPropagation(); } From fe857b34b5f931ec1ed81b04c21440fb2a0b77bf Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 29 Jul 2024 12:01:40 +0300 Subject: [PATCH 03/29] Fixed Modbus Slave Config Values visibility --- .../modbus/modbus-values/modbus-values.component.scss | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-values/modbus-values.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-values/modbus-values.component.scss index 2d0782e6a5..e80998b88a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-values/modbus-values.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-values/modbus-values.component.scss @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -:host { - .mat-mdc-tab-body-wrapper { - min-height: 320px; - } + +:host ::ng-deep .mat-mdc-tab-body-wrapper { + min-height: 320px; } ::ng-deep .mdc-evolution-chip-set__chips { From d283db3bb5e824878056b796e7eddd2afa06f7d0 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 29 Jul 2024 17:37:57 +0300 Subject: [PATCH 04/29] Updated Form for Mobdus RPC templates --- .../modbus-data-keys-panel.component.html | 2 +- .../modbus-data-keys-panel.component.ts | 5 +- .../modbus-rpc-parameters.component.html | 75 ++++++++ .../modbus-rpc-parameters.component.ts | 166 ++++++++++++++++++ ...teway-service-rpc-connector.component.html | 40 ----- ...gateway-service-rpc-connector.component.ts | 27 +-- .../gateway-service-rpc.component.html | 28 ++- .../gateway-service-rpc.component.scss | 4 + .../gateway/gateway-service-rpc.component.ts | 4 + .../lib/gateway/gateway-widget.models.ts | 53 ++---- .../widget/widget-components.module.ts | 4 + .../assets/locale/locale.constant-en_US.json | 22 ++- 12 files changed, 305 insertions(+), 125 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html create mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html index 02d2d1491d..238c6d92af 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html @@ -98,7 +98,7 @@ name="value" formControlName="objectsCount" placeholder="{{ 'gateway.set' | translate }}" - [readonly]="!editableDataTypes.includes(keyControl.get('type').value)" + [readonly]="!ModbusEditableDataTypes.includes(keyControl.get('type').value)" />
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts index 5b312f52c8..d645b4f30b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts @@ -27,6 +27,7 @@ import { import { TbPopoverComponent } from '@shared/components/popover.component'; import { ModbusDataType, + ModbusEditableDataTypes, ModbusFunctionCodeTranslationsMap, ModbusObjectCountByDataType, ModbusValue, @@ -72,7 +73,7 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { functionCodesMap = new Map(); defaultFunctionCodes = []; - readonly editableDataTypes = [ModbusDataType.BYTES, ModbusDataType.BITS, ModbusDataType.STRING]; + readonly ModbusEditableDataTypes = ModbusEditableDataTypes; readonly ModbusFunctionCodeTranslationsMap = ModbusFunctionCodeTranslationsMap; private destroy$ = new Subject(); @@ -161,7 +162,7 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { private observeKeyDataType(keyFormGroup: FormGroup): void { keyFormGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(dataType => { - if (!this.editableDataTypes.includes(dataType)) { + if (!this.ModbusEditableDataTypes.includes(dataType)) { keyFormGroup.get('objectsCount').patchValue(ModbusObjectCountByDataType[dataType], {emitEvent: false}); } this.updateFunctionCodes(keyFormGroup, dataType); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html new file mode 100644 index 0000000000..426121c223 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html @@ -0,0 +1,75 @@ + +
+ + {{ 'gateway.key' | translate }} + + + warning + + +
+
+ + {{ 'gateway.rpc.type' | translate }} + + {{ type }} + + + + {{ 'gateway.rpc.functionCode' | translate }} + + {{ ModbusFunctionCodeTranslationsMap.get(code) | translate}} + + +
+
+ + {{ 'gateway.rpc.value' | translate }} + + + warning + + +
+
+ + {{ 'gateway.rpc.address' | translate }} + + + warning + + + + {{ 'gateway.rpc.objectsCount' | translate }} + + +
+
+ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts new file mode 100644 index 0000000000..17c48cc595 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.ts @@ -0,0 +1,166 @@ +/// +/// Copyright © 2016-2024 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 { + ChangeDetectionStrategy, + Component, + forwardRef, + OnDestroy, +} from '@angular/core'; +import { + ControlValueAccessor, + FormBuilder, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + UntypedFormGroup, + ValidationErrors, + Validator, + Validators +} from '@angular/forms'; +import { SharedModule } from '@shared/shared.module'; +import { CommonModule } from '@angular/common'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; +import { + ModbusDataType, + ModbusEditableDataTypes, + ModbusFunctionCodeTranslationsMap, + ModbusObjectCountByDataType, + ModbusValue, + noLeadTrailSpacesRegex, +} from '@home/components/widget/lib/gateway/gateway-widget.models'; + +@Component({ + selector: 'tb-modbus-rpc-parameters', + templateUrl: './modbus-rpc-parameters.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => ModbusRpcParametersComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ModbusRpcParametersComponent), + multi: true + } + ], + standalone: true, + imports: [ + CommonModule, + SharedModule, + ], +}) +export class ModbusRpcParametersComponent implements ControlValueAccessor, Validator, OnDestroy { + + rpcParametersFormGroup: UntypedFormGroup; + functionCodes: Array; + + readonly ModbusEditableDataTypes = ModbusEditableDataTypes; + readonly ModbusFunctionCodeTranslationsMap = ModbusFunctionCodeTranslationsMap; + + readonly modbusDataTypes = Object.values(ModbusDataType) as ModbusDataType[]; + readonly writeFunctionCodes = [5, 6, 15, 16]; + + private readonly defaultFunctionCodes = [3, 4, 6, 16]; + private readonly readFunctionCodes = [1, 2, 3, 4]; + private readonly bitsFunctionCodes = [...this.readFunctionCodes, ...this.writeFunctionCodes]; + + private onChange: (value: ModbusValue) => void; + private onTouched: () => void; + + private destroy$ = new Subject(); + + constructor(private fb: FormBuilder) { + this.rpcParametersFormGroup = this.fb.group({ + tag: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], + type: [ModbusDataType.BYTES, [Validators.required]], + functionCode: [this.defaultFunctionCodes[0], [Validators.required]], + value: [{value: '', disabled: true}, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], + address: [null, [Validators.required]], + objectsCount: [1, [Validators.required]], + }); + + this.updateFunctionCodes(this.rpcParametersFormGroup.get('type').value); + this.observeValueChanges(); + this.observeKeyDataType(); + this.observeFunctionCode(); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + + registerOnChange(fn: (value: ModbusValue) => void): void { + this.onChange = fn; + } + + registerOnTouched(fn: () => void): void { + this.onTouched = fn; + } + + validate(): ValidationErrors | null { + return this.rpcParametersFormGroup.valid ? null : { + rpcParametersFormGroup: { valid: false } + }; + } + + writeValue(value: ModbusValue): void { + this.rpcParametersFormGroup.patchValue(value, {emitEvent: false}); + } + + private observeValueChanges(): void { + this.rpcParametersFormGroup.valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + this.onChange(value); + this.onTouched(); + }); + } + + private observeKeyDataType(): void { + this.rpcParametersFormGroup.get('type').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(dataType => { + if (!this.ModbusEditableDataTypes.includes(dataType)) { + this.rpcParametersFormGroup.get('objectsCount').patchValue(ModbusObjectCountByDataType[dataType], {emitEvent: false}); + } + this.updateFunctionCodes(dataType); + }); + } + + private observeFunctionCode(): void { + this.rpcParametersFormGroup.get('functionCode').valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(code => this.updateValueEnabling(code)); + } + + private updateValueEnabling(code: number): void { + if (this.writeFunctionCodes.includes(code)) { + this.rpcParametersFormGroup.get('value').enable({emitEvent: false}); + } else { + this.rpcParametersFormGroup.get('value').setValue(null); + this.rpcParametersFormGroup.get('value').disable({emitEvent: false}); + } + } + + private updateFunctionCodes(dataType: ModbusDataType): void { + this.functionCodes = dataType === ModbusDataType.BITS ? this.bitsFunctionCodes : this.defaultFunctionCodes; + if (!this.functionCodes.includes(this.rpcParametersFormGroup.get('functionCode').value)) { + this.rpcParametersFormGroup.get('functionCode').patchValue(this.functionCodes[0], {emitEvent: false}); + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html index eb428bebdc..3e94ae96d7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.html @@ -50,46 +50,6 @@ placeholder="${params}"/> - - - {{ 'gateway.rpc.tag' | translate }} - - -
- - {{ 'gateway.rpc.type' | translate }} - - - {{ type }} - - - - - {{ 'gateway.rpc.functionCode' | translate }} - - - {{ modbusCodesTranslate.get(code) | translate}} - - - -
- - {{ 'gateway.rpc.value' | translate }} - - -
- - {{ 'gateway.rpc.address' | translate }} - - - - {{ 'gateway.rpc.objectsCount' | translate }} - - -
-
{{ 'gateway.rpc.methodRPC' | translate }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts index 3027cafa8d..989f9daeed 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc-connector.component.ts @@ -35,8 +35,6 @@ import { ConnectorType, GatewayConnectorDefaultTypesTranslatesMap, HTTPMethods, - ModbusCodesTranslate, - ModbusCommandTypes, noLeadTrailSpacesRegex, RPCCommand, RPCTemplateConfig, @@ -53,7 +51,7 @@ import { } from '@shared/components/dialog/json-object-edit-dialog.component'; import { jsonRequired } from '@shared/components/json-object-edit.component'; import { deepClone } from '@core/utils'; -import { filter, takeUntil, tap } from "rxjs/operators"; +import { takeUntil, tap } from "rxjs/operators"; import { Subject } from "rxjs"; @Component({ @@ -80,9 +78,7 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, OnDestroy, C saveTemplate: EventEmitter = new EventEmitter(); commandForm: FormGroup; - codesArray: Array = [1, 2, 3, 4, 5, 6, 15, 16]; ConnectorType = ConnectorType; - modbusCommandTypes = Object.values(ModbusCommandTypes) as ModbusCommandTypes[]; bACnetRequestTypes = Object.values(BACnetRequestTypes) as BACnetRequestTypes[]; bACnetObjectTypes = Object.values(BACnetObjectTypes) as BACnetObjectTypes[]; bLEMethods = Object.values(BLEMethods) as BLEMethods[]; @@ -98,7 +94,6 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, OnDestroy, C SocketMethodProcessingsTranslates = SocketMethodProcessingsTranslates; SNMPMethodsTranslations = SNMPMethodsTranslations; gatewayConnectorDefaultTypesTranslates = GatewayConnectorDefaultTypesTranslatesMap; - modbusCodesTranslate = ModbusCodesTranslate; urlPattern = /^[-a-zA-Zd_$:{}?~+=\/.0-9-]*$/; numbersOnlyPattern = /^[0-9]*$/; @@ -156,26 +151,6 @@ export class GatewayServiceRPCConnectorComponent implements OnInit, OnDestroy, C withResponse: [false, []], }); break; - case ConnectorType.MODBUS: - formGroup = this.fb.group({ - tag: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], - type: [null, [Validators.required]], - functionCode: [null, [Validators.required]], - value: [null, []], - address: [null, [Validators.required, Validators.min(0), Validators.pattern(this.numbersOnlyPattern)]], - objectsCount: [null, [Validators.required, Validators.min(0), Validators.pattern(this.numbersOnlyPattern)]] - }) - const valueForm = formGroup.get('value'); - formGroup.get('functionCode').valueChanges.subscribe(value => { - if (value > 4) { - valueForm.addValidators([Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]); - } else { - valueForm.clearValidators(); - valueForm.setValue(null); - } - valueForm.updateValueAndValidity(); - }) - break; case ConnectorType.BACNET: formGroup = this.fb.group({ method: [null, [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html index 8368698087..41dea0b656 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.html @@ -41,8 +41,32 @@
- + + +
+
{{ 'gateway.rpc.title' | translate: {type: gatewayConnectorDefaultTypesTranslates.get(connectorType)} }}
+ +
+ + +
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss index f74097bbba..b8424dc068 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.scss @@ -40,6 +40,10 @@ } } + .rpc-parameters { + width: 100%; + } + .result-block { padding: 0 5px; display: flex; diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts index 1f3327ec06..d6b20d0137 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-service-rpc.component.ts @@ -22,6 +22,7 @@ import { ContentType } from '@shared/models/constants'; import { jsonRequired } from '@shared/components/json-object-edit.component'; import { ConnectorType, + GatewayConnectorDefaultTypesTranslatesMap, RPCCommand, RPCTemplate, RPCTemplateConfig, @@ -71,6 +72,9 @@ export class GatewayServiceRPCComponent implements OnInit { public connectorType: ConnectorType; public templates: Array = []; + readonly ConnectorType = ConnectorType; + readonly gatewayConnectorDefaultTypesTranslates = GatewayConnectorDefaultTypesTranslatesMap; + private subscription: IWidgetSubscription; private subscriptionOptions: WidgetSubscriptionOptions = { callbacks: { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 8df3994ea2..0cafb185f4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -311,35 +311,15 @@ export interface RPCCommand { time: number; } - -export enum ModbusCommandTypes { - Bits = 'bits', - Bit = 'bit', - // eslint-disable-next-line id-blacklist - String = 'string', - Bytes = 'bytes', - Int8 = '8int', - Uint8 = '8uint', - Int16 = '16int', - Uint16 = '16uint', - Float16 = '16float', - Int32 = '32int', - Uint32 = '32uint', - Float32 = '32float', - Int64 = '64int', - Uint64 = '64uint', - Float64 = '64float' -} - -export const ModbusCodesTranslate = new Map([ - [1, 'gateway.rpc.read-coils'], - [2, 'gateway.rpc.read-discrete-inputs'], - [3, 'gateway.rpc.read-multiple-holding-registers'], - [4, 'gateway.rpc.read-input-registers'], - [5, 'gateway.rpc.write-single-coil'], - [6, 'gateway.rpc.write-single-holding-register'], - [15, 'gateway.rpc.write-multiple-coils'], - [16, 'gateway.rpc.write-multiple-holding-registers'] +export const ModbusFunctionCodeTranslationsMap = new Map([ + [1, 'gateway.function-codes.read-coils'], + [2, 'gateway.function-codes.read-discrete-inputs'], + [3, 'gateway.function-codes.read-multiple-holding-registers'], + [4, 'gateway.function-codes.read-input-registers'], + [5, 'gateway.function-codes.write-single-coil'], + [6, 'gateway.function-codes.write-single-holding-register'], + [15, 'gateway.function-codes.write-multiple-coils'], + [16, 'gateway.function-codes.write-multiple-holding-registers'] ]); export enum BACnetRequestTypes { @@ -862,6 +842,8 @@ export enum ModbusDataType { FLOAT64 = '64float' } +export const ModbusEditableDataTypes = [ModbusDataType.BYTES, ModbusDataType.BITS, ModbusDataType.STRING]; + export enum ModbusObjectCountByDataType { '8int' = 1, '8uint' = 1, @@ -920,19 +902,6 @@ export const ModbusKeysNoKeysTextTranslationsMap = new Map( - [ - [1, 'gateway.read-coils'], - [2, 'gateway.read-discrete-inputs'], - [3, 'gateway.read-multiple-holding-registers'], - [4, 'gateway.read-input-registers'], - [5, 'gateway.write-coil'], - [6, 'gateway.write-register'], - [15, 'gateway.write-coils'], - [16, 'gateway.write-registers'], - ] -); - export interface ModbusMasterConfig { slaves: SlaveConfig[]; } diff --git a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts index 51d82dece9..db6b7543a4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/widget/widget-components.module.ts @@ -141,6 +141,9 @@ import { import { TypeValuePanelComponent } from '@home/components/widget/lib/gateway/connectors-configuration/type-value-panel/type-value-panel.component'; +import { + ModbusRpcParametersComponent +} from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component'; @NgModule({ declarations: [ @@ -227,6 +230,7 @@ import { KeyValueIsNotEmptyPipe, ModbusBasicConfigComponent, EllipsisChipListDirective, + ModbusRpcParametersComponent, ], exports: [ EntitiesTableWidgetComponent, diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 14eb272910..e99c652721 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -2914,6 +2914,16 @@ "from-device-request-settings": "Input request parsing", "from-device-request-settings-hint": "These fields support JSONPath expressions to extract a name from incoming message.", "function-code": "Function code", + "function-codes": { + "read-coils": "01 - Read Coils", + "read-discrete-inputs": "02 - Read Discrete Inputs", + "read-multiple-holding-registers": "03 - Read Multiple Holding Registers", + "read-input-registers": "04 - Read Input Registers", + "write-single-coil": "05 - Write Single Coil", + "write-single-holding-register": "06 - Write Single Holding Register", + "write-multiple-coils": "15 - Write Multiple Coils", + "write-multiple-holding-registers": "16 - Write Multiple Holding Registers" + }, "to-device-response-settings": "Output request processing", "to-device-response-settings-hint": "For these fields you can use the following variables and they will be replaced with actual values: ${deviceName}, ${attributeKey}, ${attributeValue}", "gateway": "Gateway", @@ -3120,14 +3130,6 @@ "template-name-duplicate": "Template with such name already exists, it will be updated.", "command": "Command", "params": "Params", - "read-coils": "01: Read Coils", - "read-discrete-inputs": "02: Read Discrete Inputs", - "read-multiple-holding-registers": "03: Read Multiple Holding Registers", - "read-input-registers": "04: Read Input Registers", - "write-single-coil": "05: Write Single Coil", - "write-single-holding-register": "06: Write Single Holding Register", - "write-multiple-coils": "15: Write Multiple Coils", - "write-multiple-holding-registers": "16: Write Multiple Holding Registers", "json-value-invalid": "JSON value has an invalid format" }, "rpc-methods": "RPC methods", @@ -3317,10 +3319,6 @@ "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", - "read-input-registers": "Read Input Registers", "write-coil": "Write Coil", "write-coils": "Write Coils", "write-register": "Write Register", From 8ca608cdb90c01ab2457604f483e5568272b3be3 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 29 Jul 2024 17:43:34 +0300 Subject: [PATCH 05/29] license --- .../modbus-rpc-parameters.component.html | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html index 426121c223..c2dead1abc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-rpc-parameters/modbus-rpc-parameters.component.html @@ -1,3 +1,20 @@ +
From 635f48d3434f93acdb523025dd2ac92dffb41e3e Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 30 Jul 2024 12:10:27 +0300 Subject: [PATCH 06/29] Reworked validation of Mosbus tabs --- .../modbus-basic-config.component.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 1fca768980..bfd085a4c4 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -24,7 +24,7 @@ import { ValidationErrors, Validator, } from '@angular/forms'; -import { ConnectorType, ModbusBasicConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; +import { ModbusBasicConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { SharedModule } from '@shared/shared.module'; import { CommonModule } from '@angular/common'; import { takeUntil } from 'rxjs/operators'; @@ -109,8 +109,14 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat } validate(): ValidationErrors | null { - return this.basicFormGroup.valid ? null : { - basicFormGroup: {valid: false} - }; + const masterHasSlaves = !!this.basicFormGroup.get('master').value.slaves?.length; + const slaveEnabled = this.basicFormGroup.get('slave').value.sendDataToThingsBoard; + const slaveIsValid = this.basicFormGroup.get('slave').valid; + + if ((slaveEnabled && slaveIsValid) || (masterHasSlaves && !slaveEnabled)) { + return null; + } + + return { basicFormGroup: { valid: false } }; } } From a4ee0f6d4c9c60f3b6e3b5de69cb4addb7697378 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 30 Jul 2024 12:59:18 +0300 Subject: [PATCH 07/29] refactoring --- .../modbus-basic-config/modbus-basic-config.component.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index bfd085a4c4..61e5677e9f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -21,6 +21,7 @@ import { FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, + UntypedFormControl, ValidationErrors, Validator, } from '@angular/forms'; @@ -108,9 +109,9 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } - validate(): ValidationErrors | null { - const masterHasSlaves = !!this.basicFormGroup.get('master').value.slaves?.length; - const slaveEnabled = this.basicFormGroup.get('slave').value.sendDataToThingsBoard; + validate(basicConfigControl: UntypedFormControl): ValidationErrors | null { + const masterHasSlaves = !!basicConfigControl.value.master?.slaves?.length; + const slaveEnabled = basicConfigControl.value.slave?.sendDataToThingsBoard; const slaveIsValid = this.basicFormGroup.get('slave').valid; if ((slaveEnabled && slaveIsValid) || (masterHasSlaves && !slaveEnabled)) { From 322e90610d388190ab3c27275457867abbfc8cb5 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 30 Jul 2024 15:46:47 +0300 Subject: [PATCH 08/29] Fixed saving validation on creating empty OPC connector --- .../broker-config-control.component.ts | 13 ++++---- .../opc-server-config.component.ts | 31 ++++++++++++------- .../lib/gateway/gateway-widget.models.ts | 1 + 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts index f7d37b167e..d4bfdd4694 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/broker-config-control/broker-config-control.component.ts @@ -109,12 +109,13 @@ export class BrokerConfigControlComponent implements ControlValueAccessor, Valid } writeValue(brokerConfig: BrokerConfig): void { - const brokerConfigState = { - ...brokerConfig, - version: brokerConfig.version || 5, - clientId: brokerConfig.clientId || 'tb_gw_' + generateSecret(5), - }; - this.brokerConfigFormGroup.reset(brokerConfigState, {emitEvent: false}); + const { + version = 5, + clientId = `tb_gw_${generateSecret(5)}`, + security = {}, + } = brokerConfig; + + this.brokerConfigFormGroup.reset({ ...brokerConfig, version, clientId, security }, { emitEvent: false }); this.cdr.markForCheck(); } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.ts index eddad255a3..ff50480b92 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/opc-server-config/opc-server-config.component.ts @@ -85,7 +85,7 @@ export class OpcServerConfigComponent implements ControlValueAccessor, Validator subCheckPeriodInMillis: [10, [Validators.required, Validators.min(10)]], showMap: [false, []], security: [SecurityPolicy.BASIC128, []], - identity: [{}, [Validators.required]] + identity: [] }); this.serverConfigFormGroup.valueChanges.pipe( @@ -116,16 +116,25 @@ export class OpcServerConfigComponent implements ControlValueAccessor, Validator } writeValue(serverConfig: ServerConfig): void { - const { timeoutInMillis, scanPeriodInMillis, enableSubscriptions, subCheckPeriodInMillis, showMap, security } = serverConfig; - const serverConfigState = { + const { + timeoutInMillis = 1000, + scanPeriodInMillis = 1000, + enableSubscriptions = true, + subCheckPeriodInMillis = 10, + showMap = false, + security = SecurityPolicy.BASIC128, + identity = {}, + } = serverConfig; + + this.serverConfigFormGroup.reset({ ...serverConfig, - timeoutInMillis: timeoutInMillis || 1000, - scanPeriodInMillis: scanPeriodInMillis || 1000, - enableSubscriptions: enableSubscriptions || true, - subCheckPeriodInMillis: subCheckPeriodInMillis || 10, - showMap: showMap || false, - security: security || SecurityPolicy.BASIC128, - }; - this.serverConfigFormGroup.reset(serverConfigState, {emitEvent: false}); + timeoutInMillis, + scanPeriodInMillis, + enableSubscriptions, + subCheckPeriodInMillis, + showMap, + security, + identity, + }, { emitEvent: false }); } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 8df3994ea2..18e4d31496 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -170,6 +170,7 @@ export interface ConnectorSecurity { pathToCACert?: string; pathToPrivateKey?: string; pathToClientCert?: string; + mode?: ModeType; } export type ConnectorMapping = DeviceConnectorMapping | RequestMappingData | ConverterConnectorMapping; From 1dddce5171055222203e08b9fd0885e70d9be365 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 30 Jul 2024 17:45:42 +0300 Subject: [PATCH 09/29] Changed approach of enable button --- .../modbus-basic-config.component.html | 10 +++++ .../modbus-basic-config.component.scss | 6 --- .../modbus-basic-config.component.ts | 22 ++++++++++- .../modbus-master-table.component.ts | 6 +-- .../modbus-slave-config.component.html | 17 ++++----- .../modbus-slave-config.component.scss | 27 -------------- .../modbus-slave-config.component.ts | 37 ++++++++----------- 7 files changed, 55 insertions(+), 70 deletions(-) delete mode 100644 ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.scss diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html index 17f5185bc6..105a3c0e8e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html @@ -23,6 +23,16 @@ +
+
{{ 'gateway.hints.modbus-server' | translate }}
+
+ + + {{ 'gateway.enable' | translate }} + + +
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss index b70fe42401..3b7e7288c8 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.scss @@ -16,9 +16,3 @@ :host { height: 100%; } - -:host ::ng-deep { - .mat-mdc-tab-body-content { - overflow: hidden !important; - } -} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 61e5677e9f..d5465f7b5c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -18,6 +18,7 @@ import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, Templ import { ControlValueAccessor, FormBuilder, + FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, @@ -34,6 +35,7 @@ import { Subject } from 'rxjs'; import { EllipsisChipListDirective } from '@shared/directives/ellipsis-chip-list.directive'; import { ModbusSlaveConfigComponent } from '../modbus-slave-config/modbus-slave-config.component'; import { ModbusMasterTableComponent } from '../modbus-master-table/modbus-master-table.component'; +import { isEqual } from '@core/utils'; @Component({ selector: 'tb-modbus-basic-config', @@ -67,6 +69,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat @Input() generalTabContent: TemplateRef; basicFormGroup: FormGroup; + enableSlaveControl: FormControl; onChange: (value: ModbusBasicConfig) => void; onTouched: () => void; @@ -78,6 +81,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat master: [], slave: [], }); + this.enableSlaveControl = new FormControl(false); this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) @@ -85,6 +89,13 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat this.onChange(value); this.onTouched(); }); + + this.enableSlaveControl.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(enable => { + this.updateSlaveEnabling(enable); + this.basicFormGroup.get('slave').updateValueAndValidity(); + }); } ngOnDestroy(): void { @@ -107,11 +118,12 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat }; this.basicFormGroup.setValue(editedBase, {emitEvent: false}); + this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); } validate(basicConfigControl: UntypedFormControl): ValidationErrors | null { const masterHasSlaves = !!basicConfigControl.value.master?.slaves?.length; - const slaveEnabled = basicConfigControl.value.slave?.sendDataToThingsBoard; + const slaveEnabled = this.enableSlaveControl.value; const slaveIsValid = this.basicFormGroup.get('slave').valid; if ((slaveEnabled && slaveIsValid) || (masterHasSlaves && !slaveEnabled)) { @@ -120,4 +132,12 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat return { basicFormGroup: { valid: false } }; } + + private updateSlaveEnabling(isEnabled: boolean): void { + if (isEnabled) { + this.basicFormGroup.get('slave').enable({emitEvent: false}); + } else { + this.basicFormGroup.get('slave').disable({emitEvent: false}); + } + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 2cb66f6062..6a36f9a829 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -45,7 +45,7 @@ import { ModbusProtocolLabelsMap, SlaveConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; -import { isDefinedAndNotNull, isUndefinedOrNull } from '@core/utils'; +import { isDefinedAndNotNull } from '@core/utils'; import { SharedModule } from '@shared/shared.module'; import { CommonModule } from '@angular/common'; import { ModbusSlaveDialogComponent } from '../modbus-slave-dialog/modbus-slave-dialog.component'; @@ -139,9 +139,7 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat } validate(): ValidationErrors | null { - return this.slaves.controls.length ? null : { - slavesFormGroup: {valid: false} - }; + return null; } enterFilterMode(): void { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html index d37c8cc9ee..a46dd68edc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html @@ -16,16 +16,6 @@ -->
-
-
{{ 'gateway.hints.modbus-server' | translate }}
-
- - - {{ 'gateway.enable' | translate }} - - -
-
gateway.server-slave-config
@@ -178,6 +168,13 @@
+
+ + + {{ 'gateway.send-data-TB' | translate }} + + +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.scss deleted file mode 100644 index a464832202..0000000000 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.scss +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright © 2016-2024 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. - */ -$server-config-header-height: 132px; - -:host { - .slave-content { - height: calc(100% - #{$server-config-header-height}); - overflow: auto; - } - - .slave-container { - display: inherit; - } -} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts index 2a8488a2d4..46771c6937 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts @@ -43,7 +43,7 @@ import { import { SharedModule } from '@shared/shared.module'; import { CommonModule } from '@angular/common'; import { Subject } from 'rxjs'; -import { startWith, takeUntil } from 'rxjs/operators'; +import { takeUntil } from 'rxjs/operators'; import { GatewayPortTooltipPipe } from '@home/components/widget/lib/gateway/pipes/gateway-port-tooltip.pipe'; import { ModbusSecurityConfigComponent } from '../modbus-security-config/modbus-security-config.component'; import { ModbusValuesComponent, } from '../modbus-values/modbus-values.component'; @@ -73,7 +73,6 @@ import { isEqual } from '@core/utils'; ModbusSecurityConfigComponent, GatewayPortTooltipPipe, ], - styleUrls: ['./modbus-slave-config.component.scss'], }) export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validator, OnDestroy { @@ -90,6 +89,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat readonly ModbusProtocolType = ModbusProtocolType; readonly modbusBaudrates = ModbusBaudrates; + private isSlaveEnabled = false; private readonly serialSpecificControlKeys = ['serialPort', 'baudrate']; private readonly tcpUdpSpecificControlKeys = ['port', 'security', 'host']; @@ -126,14 +126,9 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.observeValueChanges(); this.observeTypeChange(); - this.observeFormEnable(); this.observeShowSecurity(); } - get isSlaveEnabled(): boolean { - return this.slaveConfigFormGroup.get('sendDataToThingsBoard').value; - } - get protocolType(): ModbusProtocolType { return this.slaveConfigFormGroup.get('type').value; } @@ -160,7 +155,11 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat writeValue(slaveConfig: ModbusSlave): void { this.showSecurityControl.patchValue(!!slaveConfig.security && !isEqual(slaveConfig.security, {})); this.updateSlaveConfig(slaveConfig); - this.updateFormEnableState(slaveConfig.sendDataToThingsBoard); + } + + setDisabledState(isDisabled: boolean): void { + this.isSlaveEnabled = !isDisabled; + this.updateFormEnableState(); } private observeValueChanges(): void { @@ -180,7 +179,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.slaveConfigFormGroup.get('type').valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(type => { - this.updateFormEnableState(this.isSlaveEnabled); + this.updateFormEnableState(); this.updateMethodType(type); }); } @@ -196,22 +195,15 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } } - private observeFormEnable(): void { - this.slaveConfigFormGroup.get('sendDataToThingsBoard').valueChanges - .pipe(startWith(this.isSlaveEnabled), takeUntil(this.destroy$)) - .subscribe(value => this.updateFormEnableState(value)); - } - - private updateFormEnableState(enabled: boolean): void { - if (enabled) { + private updateFormEnableState(): void { + if (this.isSlaveEnabled) { this.slaveConfigFormGroup.enable({emitEvent: false}); this.showSecurityControl.enable({emitEvent: false}); } else { this.slaveConfigFormGroup.disable({emitEvent: false}); this.showSecurityControl.disable({emitEvent: false}); - this.slaveConfigFormGroup.get('sendDataToThingsBoard').enable({emitEvent: false}); } - this.updateEnablingByProtocol(this.protocolType); + this.updateEnablingByProtocol(); this.updateSecurityEnable(this.showSecurityControl.value); } @@ -229,9 +221,10 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } } - private updateEnablingByProtocol(type: ModbusProtocolType): void { - const enableKeys = type === ModbusProtocolType.Serial ? this.serialSpecificControlKeys : this.tcpUdpSpecificControlKeys; - const disableKeys = type === ModbusProtocolType.Serial ? this.tcpUdpSpecificControlKeys : this.serialSpecificControlKeys; + private updateEnablingByProtocol(): void { + const isSerial = this.protocolType === ModbusProtocolType.Serial; + const enableKeys = isSerial ? this.serialSpecificControlKeys : this.tcpUdpSpecificControlKeys; + const disableKeys = isSerial ? this.tcpUdpSpecificControlKeys : this.serialSpecificControlKeys; if (this.isSlaveEnabled) { enableKeys.forEach(key => this.slaveConfigFormGroup.get(key)?.enable({ emitEvent: false })); From d9a733c1840ddb3cfe7f3f5584572d7796dc33a0 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 30 Jul 2024 17:49:11 +0300 Subject: [PATCH 10/29] refactoring --- .../modbus-master-table.component.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 6a36f9a829..5838540d65 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -34,11 +34,8 @@ import { ControlValueAccessor, FormArray, FormBuilder, - NG_VALIDATORS, NG_VALUE_ACCESSOR, UntypedFormGroup, - ValidationErrors, - Validator, } from '@angular/forms'; import { ModbusMasterConfig, @@ -61,17 +58,12 @@ import { TbTableDatasource } from '@shared/components/table/table-datasource.abs provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ModbusMasterTableComponent), multi: true - }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ModbusMasterTableComponent), - multi: true } ], standalone: true, imports: [CommonModule, SharedModule] }) -export class ModbusMasterTableComponent implements ControlValueAccessor, Validator, AfterViewInit, OnInit, OnDestroy { +export class ModbusMasterTableComponent implements ControlValueAccessor, AfterViewInit, OnInit, OnDestroy { @ViewChild('searchInput') searchInputField: ElementRef; @@ -138,10 +130,6 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat this.pushDataAsFormArrays(master.slaves); } - validate(): ValidationErrors | null { - return null; - } - enterFilterMode(): void { this.textSearchMode = true; this.cdr.detectChanges(); From a8f6e2c4d2a7dec9cb1fc01d5f659f1661c35e65 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 30 Jul 2024 18:18:33 +0300 Subject: [PATCH 11/29] refactoring --- .../modbus/modbus-basic-config/modbus-basic-config.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index d5465f7b5c..87aef8d43e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -94,7 +94,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat .pipe(takeUntil(this.destroy$)) .subscribe(enable => { this.updateSlaveEnabling(enable); - this.basicFormGroup.get('slave').updateValueAndValidity(); + this.basicFormGroup.get('slave').updateValueAndValidity({emitEvent: !!this.onChange}); }); } From c1d3ac8f437de1fb83eb4edc97aeea5e09d8983c Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 30 Jul 2024 18:24:44 +0300 Subject: [PATCH 12/29] refactoring --- .../modbus/modbus-basic-config/modbus-basic-config.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 87aef8d43e..e85d9d31c0 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -124,7 +124,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat validate(basicConfigControl: UntypedFormControl): ValidationErrors | null { const masterHasSlaves = !!basicConfigControl.value.master?.slaves?.length; const slaveEnabled = this.enableSlaveControl.value; - const slaveIsValid = this.basicFormGroup.get('slave').valid; + const slaveIsValid = this.basicFormGroup.valid; if ((slaveEnabled && slaveIsValid) || (masterHasSlaves && !slaveEnabled)) { return null; From 4ff73d3777bdf31c8005500aa6cc58e66c86beff Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 31 Jul 2024 11:12:40 +0300 Subject: [PATCH 13/29] Modbus minor UI adjustments --- .../modbus-data-keys-panel.component.html | 14 +++++++---- .../modbus-data-keys-panel.component.scss | 5 +--- .../modbus-data-keys-panel.component.ts | 23 +++++++++++-------- .../modbus-master-table.component.html | 3 +++ .../modbus-master-table.component.ts | 2 +- .../modbus-slave-dialog.component.html | 2 +- .../modbus-slave-dialog.component.scss | 5 ++++ .../assets/locale/locale.constant-en_US.json | 3 ++- 8 files changed, 35 insertions(+), 22 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html index 02d2d1491d..4f71ebc19c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.html @@ -26,12 +26,16 @@ -
- - {{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }} - - {{ keyControl.get('tag').value }} +
+ {{ keyControl.get('tag').value }}{{ '-' }}{{ keyControl.get('value').value }}
+ +
+
{{ 'gateway.key' | translate }}: {{ keyControl.get('tag').value }}
+
{{ 'gateway.address' | translate }}: {{ keyControl.get('address').value }}
+
{{ 'gateway.type' | translate }}: {{ keyControl.get('type').value }}
+
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss index 0e9f9a432f..d9ef45d66b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss @@ -20,10 +20,7 @@ max-width: 700px; .title-container { - max-width: 11vw; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap + width: 12vw; } .key-panel { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts index 5b312f52c8..304495e8d9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.ts @@ -40,6 +40,7 @@ import { generateSecret } from '@core/utils'; import { coerceBoolean } from '@shared/decorators/coercion'; import { takeUntil } from 'rxjs/operators'; import { Subject } from 'rxjs'; +import { TruncateWithTooltipDirective } from '@shared/directives/truncate-with-tooltip.directive'; @Component({ selector: 'tb-modbus-data-keys-panel', @@ -50,6 +51,7 @@ import { Subject } from 'rxjs'; CommonModule, SharedModule, GatewayHelpLinkPipe, + TruncateWithTooltipDirective, ] }) export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { @@ -78,8 +80,9 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { private destroy$ = new Subject(); private readonly defaultReadFunctionCodes = [3, 4]; - private readonly defaultWriteFunctionCodes = [5, 6, 15, 16]; - private readonly stringAttrUpdatesWriteFunctionCodes = [6, 16]; + private readonly bitsReadFunctionCodes = [1, 2]; + private readonly defaultWriteFunctionCodes = [6, 16]; + private readonly bitsWriteFunctionCodes = [5, 15]; constructor(private fb: UntypedFormBuilder) {} @@ -177,23 +180,23 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy { } private getFunctionCodes(dataType: ModbusDataType): number[] { + const writeFunctionCodes = [ + ...(dataType === ModbusDataType.BITS ? this.bitsWriteFunctionCodes : []), ...this.defaultWriteFunctionCodes + ]; + if (this.keysType === ModbusValueKey.ATTRIBUTES_UPDATES) { - return dataType === ModbusDataType.STRING - ? this.stringAttrUpdatesWriteFunctionCodes - : this.defaultWriteFunctionCodes; + return writeFunctionCodes.sort((a, b) => a - b); } const functionCodes = [...this.defaultReadFunctionCodes]; if (dataType === ModbusDataType.BITS) { - const bitsFunctionCodes = [1, 2]; - functionCodes.push(...bitsFunctionCodes); - functionCodes.sort(); + functionCodes.push(...this.bitsReadFunctionCodes); } if (this.keysType === ModbusValueKey.RPC_REQUESTS) { - functionCodes.push(...this.defaultWriteFunctionCodes); + functionCodes.push(...writeFunctionCodes); } - return functionCodes; + return functionCodes.sort((a, b) => a - b); } private getDefaultFunctionCodes(): number[] { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html index e16aa0c51f..0da32e8338 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.html @@ -16,6 +16,9 @@ -->
+
+
{{ 'gateway.hints.modbus-master' | translate }}
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 2cb66f6062..14f3635b98 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -169,7 +169,7 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { value, - buttonTitle: withIndex ? 'action.add' : 'action.apply' + buttonTitle: withIndex ? 'action.apply' : 'action.add' } }).afterClosed() .pipe(take(1), takeUntil(this.destroy$)) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html index 1e47479f03..c7fb50f146 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html @@ -28,7 +28,7 @@
-
gateway.name
+
gateway.name
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss index 8cea184957..8900741a93 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.scss @@ -18,4 +18,9 @@ width: 80vw; max-width: 900px; } + + .slave-name-label { + margin-right: 16px; + color: rgba(0, 0, 0, 0.87); + } } diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 14eb272910..2c6459582b 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -3326,7 +3326,8 @@ "write-register": "Write Register", "write-registers": "Write Registers", "hints": { - "modbus-server": "Starting with version 3.0, Gateway can run as a Modbus slave.", + "modbus-master": "Configuration sections for connecting to Modbus servers and reading data from them.", + "modbus-server": "Configuration section for the Modbus server, storing data and sending updates to the platform when changes occur or at fixed intervals.", "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", From 27bd1b2fa0ded735b05e6083ebc64474f5f0663d Mon Sep 17 00:00:00 2001 From: mpetrov Date: Wed, 31 Jul 2024 11:50:39 +0300 Subject: [PATCH 14/29] refactoring --- .../modbus-basic-config.component.ts | 16 +++++----------- .../modbus-master-table.component.ts | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index e85d9d31c0..8291558b4d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -22,7 +22,6 @@ import { FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, - UntypedFormControl, ValidationErrors, Validator, } from '@angular/forms'; @@ -95,6 +94,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat .subscribe(enable => { this.updateSlaveEnabling(enable); this.basicFormGroup.get('slave').updateValueAndValidity({emitEvent: !!this.onChange}); + this.basicFormGroup.get('master').updateValueAndValidity({emitEvent: !!this.onChange}); }); } @@ -121,16 +121,10 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); } - validate(basicConfigControl: UntypedFormControl): ValidationErrors | null { - const masterHasSlaves = !!basicConfigControl.value.master?.slaves?.length; - const slaveEnabled = this.enableSlaveControl.value; - const slaveIsValid = this.basicFormGroup.valid; - - if ((slaveEnabled && slaveIsValid) || (masterHasSlaves && !slaveEnabled)) { - return null; - } - - return { basicFormGroup: { valid: false } }; + validate(): ValidationErrors | null { + return this.basicFormGroup.valid ? null : { + basicFormGroup: {valid: false} + }; } private updateSlaveEnabling(isEnabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 5838540d65..5f51f59284 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -34,8 +34,12 @@ import { ControlValueAccessor, FormArray, FormBuilder, + NG_VALIDATORS, NG_VALUE_ACCESSOR, + UntypedFormControl, UntypedFormGroup, + ValidationErrors, + Validator, } from '@angular/forms'; import { ModbusMasterConfig, @@ -58,12 +62,17 @@ import { TbTableDatasource } from '@shared/components/table/table-datasource.abs provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ModbusMasterTableComponent), multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ModbusMasterTableComponent), + multi: true } ], standalone: true, imports: [CommonModule, SharedModule] }) -export class ModbusMasterTableComponent implements ControlValueAccessor, AfterViewInit, OnInit, OnDestroy { +export class ModbusMasterTableComponent implements ControlValueAccessor, Validator, AfterViewInit, OnInit, OnDestroy { @ViewChild('searchInput') searchInputField: ElementRef; @@ -130,6 +139,12 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, AfterVi this.pushDataAsFormArrays(master.slaves); } + validate(masterControl: UntypedFormControl): ValidationErrors | null { + return masterControl.parent.get('slave').enabled || this.slaves.controls.length ? null : { + slavesFormGroup: {valid: false} + }; + } + enterFilterMode(): void { this.textSearchMode = true; this.cdr.detectChanges(); From eb39f36007ef44a3c399cbfc1c2363492935719c Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 1 Aug 2024 11:37:58 +0300 Subject: [PATCH 15/29] refactoring --- .../modbus-basic-config.component.html | 10 ------ .../modbus-basic-config.component.ts | 32 ++++++------------- .../modbus-master-table.component.ts | 17 +--------- .../modbus-slave-config.component.html | 10 ++++++ .../modbus-slave-config.component.ts | 29 ++++++++++------- 5 files changed, 38 insertions(+), 60 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html index 105a3c0e8e..17f5185bc6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html @@ -23,16 +23,6 @@ -
-
{{ 'gateway.hints.modbus-server' | translate }}
-
- - - {{ 'gateway.enable' | translate }} - - -
-
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 8291558b4d..22430ae77c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -18,10 +18,10 @@ import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, Templ import { ControlValueAccessor, FormBuilder, - FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, + UntypedFormControl, ValidationErrors, Validator, } from '@angular/forms'; @@ -68,7 +68,6 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat @Input() generalTabContent: TemplateRef; basicFormGroup: FormGroup; - enableSlaveControl: FormControl; onChange: (value: ModbusBasicConfig) => void; onTouched: () => void; @@ -80,7 +79,6 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat master: [], slave: [], }); - this.enableSlaveControl = new FormControl(false); this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) @@ -88,14 +86,6 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat this.onChange(value); this.onTouched(); }); - - this.enableSlaveControl.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(enable => { - this.updateSlaveEnabling(enable); - this.basicFormGroup.get('slave').updateValueAndValidity({emitEvent: !!this.onChange}); - this.basicFormGroup.get('master').updateValueAndValidity({emitEvent: !!this.onChange}); - }); } ngOnDestroy(): void { @@ -118,20 +108,16 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat }; this.basicFormGroup.setValue(editedBase, {emitEvent: false}); - this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); - } - - validate(): ValidationErrors | null { - return this.basicFormGroup.valid ? null : { - basicFormGroup: {valid: false} - }; } - private updateSlaveEnabling(isEnabled: boolean): void { - if (isEnabled) { - this.basicFormGroup.get('slave').enable({emitEvent: false}); - } else { - this.basicFormGroup.get('slave').disable({emitEvent: false}); + validate(basicFormControl: UntypedFormControl): ValidationErrors | null { + const { master, slave } = basicFormControl.value; + const isEmpty = !master?.slaves?.length && (isEqual(slave, {}) || !slave); + if (!this.basicFormGroup.valid || isEmpty) { + return { + basicFormGroup: {valid: false} + }; } + return null; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 5f51f59284..75fc62ed5e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -34,12 +34,8 @@ import { ControlValueAccessor, FormArray, FormBuilder, - NG_VALIDATORS, NG_VALUE_ACCESSOR, - UntypedFormControl, UntypedFormGroup, - ValidationErrors, - Validator, } from '@angular/forms'; import { ModbusMasterConfig, @@ -63,16 +59,11 @@ import { TbTableDatasource } from '@shared/components/table/table-datasource.abs useExisting: forwardRef(() => ModbusMasterTableComponent), multi: true }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ModbusMasterTableComponent), - multi: true - } ], standalone: true, imports: [CommonModule, SharedModule] }) -export class ModbusMasterTableComponent implements ControlValueAccessor, Validator, AfterViewInit, OnInit, OnDestroy { +export class ModbusMasterTableComponent implements ControlValueAccessor, AfterViewInit, OnInit, OnDestroy { @ViewChild('searchInput') searchInputField: ElementRef; @@ -139,12 +130,6 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat this.pushDataAsFormArrays(master.slaves); } - validate(masterControl: UntypedFormControl): ValidationErrors | null { - return masterControl.parent.get('slave').enabled || this.slaves.controls.length ? null : { - slavesFormGroup: {valid: false} - }; - } - enterFilterMode(): void { this.textSearchMode = true; this.cdr.detectChanges(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html index a46dd68edc..c4986eefce 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html @@ -16,6 +16,16 @@ -->
+
+
{{ 'gateway.hints.modbus-server' | translate }}
+
+ + + {{ 'gateway.enable' | translate }} + + +
+
gateway.server-slave-config
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts index 46771c6937..86b601de53 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts @@ -77,6 +77,7 @@ import { isEqual } from '@core/utils'; export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validator, OnDestroy { slaveConfigFormGroup: UntypedFormGroup; + enableSlaveControl: FormControl; showSecurityControl: FormControl; ModbusProtocolLabelsMap = ModbusProtocolLabelsMap; ModbusMethodLabelsMap = ModbusMethodLabelsMap; @@ -89,7 +90,6 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat readonly ModbusProtocolType = ModbusProtocolType; readonly modbusBaudrates = ModbusBaudrates; - private isSlaveEnabled = false; private readonly serialSpecificControlKeys = ['serialPort', 'baudrate']; private readonly tcpUdpSpecificControlKeys = ['port', 'security', 'host']; @@ -100,6 +100,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat constructor(private fb: FormBuilder) { this.showSecurityControl = this.fb.control(false); + this.enableSlaveControl = this.fb.control(false); this.slaveConfigFormGroup = this.fb.group({ type: [ModbusProtocolType.TCP], host: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], @@ -127,6 +128,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.observeValueChanges(); this.observeTypeChange(); this.observeShowSecurity(); + this.observeFormEnable(); } get protocolType(): ModbusProtocolType { @@ -153,15 +155,11 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } writeValue(slaveConfig: ModbusSlave): void { + this.enableSlaveControl.patchValue(!!slaveConfig && !isEqual(slaveConfig, {})); this.showSecurityControl.patchValue(!!slaveConfig.security && !isEqual(slaveConfig.security, {})); this.updateSlaveConfig(slaveConfig); } - setDisabledState(isDisabled: boolean): void { - this.isSlaveEnabled = !isDisabled; - this.updateFormEnableState(); - } - private observeValueChanges(): void { this.slaveConfigFormGroup.valueChanges.pipe( takeUntil(this.destroy$) @@ -175,11 +173,20 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat }); } + private observeFormEnable(): void { + this.enableSlaveControl.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(value => { + this.updateFormEnableState(value); + this.slaveConfigFormGroup.updateValueAndValidity({emitEvent: !!this.onChange}); + }); + } + private observeTypeChange(): void { this.slaveConfigFormGroup.get('type').valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(type => { - this.updateFormEnableState(); + this.updateFormEnableState(this.enableSlaveControl.value); this.updateMethodType(type); }); } @@ -195,8 +202,8 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } } - private updateFormEnableState(): void { - if (this.isSlaveEnabled) { + private updateFormEnableState(enabled: boolean): void { + if (enabled) { this.slaveConfigFormGroup.enable({emitEvent: false}); this.showSecurityControl.enable({emitEvent: false}); } else { @@ -214,7 +221,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } private updateSecurityEnable(securityEnabled: boolean): void { - if (securityEnabled && this.isSlaveEnabled && this.protocolType !== ModbusProtocolType.Serial) { + if (securityEnabled && this.enableSlaveControl.value && this.protocolType !== ModbusProtocolType.Serial) { this.slaveConfigFormGroup.get('security').enable({emitEvent: false}); } else { this.slaveConfigFormGroup.get('security').disable({emitEvent: false}); @@ -226,7 +233,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat const enableKeys = isSerial ? this.serialSpecificControlKeys : this.tcpUdpSpecificControlKeys; const disableKeys = isSerial ? this.tcpUdpSpecificControlKeys : this.serialSpecificControlKeys; - if (this.isSlaveEnabled) { + if (this.enableSlaveControl.value) { enableKeys.forEach(key => this.slaveConfigFormGroup.get(key)?.enable({ emitEvent: false })); } From c2c54e5104d4f414721915e1931095cf1bed9887 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 1 Aug 2024 11:42:19 +0300 Subject: [PATCH 16/29] refactoring --- .../modbus-slave-config.component.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts index 86b601de53..bf1acfbf94 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts @@ -127,8 +127,8 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.observeValueChanges(); this.observeTypeChange(); - this.observeShowSecurity(); this.observeFormEnable(); + this.observeShowSecurity(); } get protocolType(): ModbusProtocolType { @@ -173,15 +173,6 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat }); } - private observeFormEnable(): void { - this.enableSlaveControl.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.updateFormEnableState(value); - this.slaveConfigFormGroup.updateValueAndValidity({emitEvent: !!this.onChange}); - }); - } - private observeTypeChange(): void { this.slaveConfigFormGroup.get('type').valueChanges .pipe(takeUntil(this.destroy$)) @@ -191,6 +182,15 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat }); } + private observeFormEnable(): void { + this.enableSlaveControl.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(value => { + this.updateFormEnableState(value); + this.slaveConfigFormGroup.updateValueAndValidity({emitEvent: !!this.onChange}); + }); + } + private updateMethodType(type: ModbusProtocolType): void { if (this.slaveConfigFormGroup.get('method').value !== ModbusMethodType.RTU) { this.slaveConfigFormGroup.get('method').patchValue( From 0a42624ba46e45a04d52417586d12337186d949c Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 1 Aug 2024 12:49:07 +0300 Subject: [PATCH 17/29] Revert "refactoring" This reverts commit c2c54e5104d4f414721915e1931095cf1bed9887. --- .../modbus-slave-config.component.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts index bf1acfbf94..86b601de53 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts @@ -127,8 +127,8 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.observeValueChanges(); this.observeTypeChange(); - this.observeFormEnable(); this.observeShowSecurity(); + this.observeFormEnable(); } get protocolType(): ModbusProtocolType { @@ -173,15 +173,6 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat }); } - private observeTypeChange(): void { - this.slaveConfigFormGroup.get('type').valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(type => { - this.updateFormEnableState(this.enableSlaveControl.value); - this.updateMethodType(type); - }); - } - private observeFormEnable(): void { this.enableSlaveControl.valueChanges .pipe(takeUntil(this.destroy$)) @@ -191,6 +182,15 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat }); } + private observeTypeChange(): void { + this.slaveConfigFormGroup.get('type').valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(type => { + this.updateFormEnableState(this.enableSlaveControl.value); + this.updateMethodType(type); + }); + } + private updateMethodType(type: ModbusProtocolType): void { if (this.slaveConfigFormGroup.get('method').value !== ModbusMethodType.RTU) { this.slaveConfigFormGroup.get('method').patchValue( From 9c0a33237aa02e12cf22a6b3c8c895dec73723ce Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 1 Aug 2024 12:49:07 +0300 Subject: [PATCH 18/29] Revert "refactoring" This reverts commit eb39f36007ef44a3c399cbfc1c2363492935719c. --- .../modbus-basic-config.component.html | 10 ++++++ .../modbus-basic-config.component.ts | 32 +++++++++++++------ .../modbus-master-table.component.ts | 17 +++++++++- .../modbus-slave-config.component.html | 10 ------ .../modbus-slave-config.component.ts | 29 +++++++---------- 5 files changed, 60 insertions(+), 38 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html index 17f5185bc6..105a3c0e8e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.html @@ -23,6 +23,16 @@ +
+
{{ 'gateway.hints.modbus-server' | translate }}
+
+ + + {{ 'gateway.enable' | translate }} + + +
+
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 22430ae77c..8291558b4d 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -18,10 +18,10 @@ import { ChangeDetectionStrategy, Component, forwardRef, Input, OnDestroy, Templ import { ControlValueAccessor, FormBuilder, + FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, - UntypedFormControl, ValidationErrors, Validator, } from '@angular/forms'; @@ -68,6 +68,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat @Input() generalTabContent: TemplateRef; basicFormGroup: FormGroup; + enableSlaveControl: FormControl; onChange: (value: ModbusBasicConfig) => void; onTouched: () => void; @@ -79,6 +80,7 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat master: [], slave: [], }); + this.enableSlaveControl = new FormControl(false); this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) @@ -86,6 +88,14 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat this.onChange(value); this.onTouched(); }); + + this.enableSlaveControl.valueChanges + .pipe(takeUntil(this.destroy$)) + .subscribe(enable => { + this.updateSlaveEnabling(enable); + this.basicFormGroup.get('slave').updateValueAndValidity({emitEvent: !!this.onChange}); + this.basicFormGroup.get('master').updateValueAndValidity({emitEvent: !!this.onChange}); + }); } ngOnDestroy(): void { @@ -108,16 +118,20 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat }; this.basicFormGroup.setValue(editedBase, {emitEvent: false}); + this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); + } + + validate(): ValidationErrors | null { + return this.basicFormGroup.valid ? null : { + basicFormGroup: {valid: false} + }; } - validate(basicFormControl: UntypedFormControl): ValidationErrors | null { - const { master, slave } = basicFormControl.value; - const isEmpty = !master?.slaves?.length && (isEqual(slave, {}) || !slave); - if (!this.basicFormGroup.valid || isEmpty) { - return { - basicFormGroup: {valid: false} - }; + private updateSlaveEnabling(isEnabled: boolean): void { + if (isEnabled) { + this.basicFormGroup.get('slave').enable({emitEvent: false}); + } else { + this.basicFormGroup.get('slave').disable({emitEvent: false}); } - return null; } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 75fc62ed5e..5f51f59284 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -34,8 +34,12 @@ import { ControlValueAccessor, FormArray, FormBuilder, + NG_VALIDATORS, NG_VALUE_ACCESSOR, + UntypedFormControl, UntypedFormGroup, + ValidationErrors, + Validator, } from '@angular/forms'; import { ModbusMasterConfig, @@ -59,11 +63,16 @@ import { TbTableDatasource } from '@shared/components/table/table-datasource.abs useExisting: forwardRef(() => ModbusMasterTableComponent), multi: true }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => ModbusMasterTableComponent), + multi: true + } ], standalone: true, imports: [CommonModule, SharedModule] }) -export class ModbusMasterTableComponent implements ControlValueAccessor, AfterViewInit, OnInit, OnDestroy { +export class ModbusMasterTableComponent implements ControlValueAccessor, Validator, AfterViewInit, OnInit, OnDestroy { @ViewChild('searchInput') searchInputField: ElementRef; @@ -130,6 +139,12 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, AfterVi this.pushDataAsFormArrays(master.slaves); } + validate(masterControl: UntypedFormControl): ValidationErrors | null { + return masterControl.parent.get('slave').enabled || this.slaves.controls.length ? null : { + slavesFormGroup: {valid: false} + }; + } + enterFilterMode(): void { this.textSearchMode = true; this.cdr.detectChanges(); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html index c4986eefce..a46dd68edc 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html @@ -16,16 +16,6 @@ -->
-
-
{{ 'gateway.hints.modbus-server' | translate }}
-
- - - {{ 'gateway.enable' | translate }} - - -
-
gateway.server-slave-config
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts index 86b601de53..46771c6937 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts @@ -77,7 +77,6 @@ import { isEqual } from '@core/utils'; export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validator, OnDestroy { slaveConfigFormGroup: UntypedFormGroup; - enableSlaveControl: FormControl; showSecurityControl: FormControl; ModbusProtocolLabelsMap = ModbusProtocolLabelsMap; ModbusMethodLabelsMap = ModbusMethodLabelsMap; @@ -90,6 +89,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat readonly ModbusProtocolType = ModbusProtocolType; readonly modbusBaudrates = ModbusBaudrates; + private isSlaveEnabled = false; private readonly serialSpecificControlKeys = ['serialPort', 'baudrate']; private readonly tcpUdpSpecificControlKeys = ['port', 'security', 'host']; @@ -100,7 +100,6 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat constructor(private fb: FormBuilder) { this.showSecurityControl = this.fb.control(false); - this.enableSlaveControl = this.fb.control(false); this.slaveConfigFormGroup = this.fb.group({ type: [ModbusProtocolType.TCP], host: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], @@ -128,7 +127,6 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat this.observeValueChanges(); this.observeTypeChange(); this.observeShowSecurity(); - this.observeFormEnable(); } get protocolType(): ModbusProtocolType { @@ -155,11 +153,15 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } writeValue(slaveConfig: ModbusSlave): void { - this.enableSlaveControl.patchValue(!!slaveConfig && !isEqual(slaveConfig, {})); this.showSecurityControl.patchValue(!!slaveConfig.security && !isEqual(slaveConfig.security, {})); this.updateSlaveConfig(slaveConfig); } + setDisabledState(isDisabled: boolean): void { + this.isSlaveEnabled = !isDisabled; + this.updateFormEnableState(); + } + private observeValueChanges(): void { this.slaveConfigFormGroup.valueChanges.pipe( takeUntil(this.destroy$) @@ -173,20 +175,11 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat }); } - private observeFormEnable(): void { - this.enableSlaveControl.valueChanges - .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.updateFormEnableState(value); - this.slaveConfigFormGroup.updateValueAndValidity({emitEvent: !!this.onChange}); - }); - } - private observeTypeChange(): void { this.slaveConfigFormGroup.get('type').valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(type => { - this.updateFormEnableState(this.enableSlaveControl.value); + this.updateFormEnableState(); this.updateMethodType(type); }); } @@ -202,8 +195,8 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } } - private updateFormEnableState(enabled: boolean): void { - if (enabled) { + private updateFormEnableState(): void { + if (this.isSlaveEnabled) { this.slaveConfigFormGroup.enable({emitEvent: false}); this.showSecurityControl.enable({emitEvent: false}); } else { @@ -221,7 +214,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat } private updateSecurityEnable(securityEnabled: boolean): void { - if (securityEnabled && this.enableSlaveControl.value && this.protocolType !== ModbusProtocolType.Serial) { + if (securityEnabled && this.isSlaveEnabled && this.protocolType !== ModbusProtocolType.Serial) { this.slaveConfigFormGroup.get('security').enable({emitEvent: false}); } else { this.slaveConfigFormGroup.get('security').disable({emitEvent: false}); @@ -233,7 +226,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat const enableKeys = isSerial ? this.serialSpecificControlKeys : this.tcpUdpSpecificControlKeys; const disableKeys = isSerial ? this.tcpUdpSpecificControlKeys : this.serialSpecificControlKeys; - if (this.enableSlaveControl.value) { + if (this.isSlaveEnabled) { enableKeys.forEach(key => this.slaveConfigFormGroup.get(key)?.enable({ emitEvent: false })); } From 17dfc0bdb0adc5c8656f12e7d36704158a97312f Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 1 Aug 2024 12:52:15 +0300 Subject: [PATCH 19/29] refactoring --- .../modbus-basic-config.component.ts | 14 ++++++++++---- .../modbus-master-table.component.ts | 17 +---------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 8291558b4d..3ed0ebf124 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -22,6 +22,7 @@ import { FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, + UntypedFormControl, ValidationErrors, Validator, } from '@angular/forms'; @@ -121,10 +122,15 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat this.enableSlaveControl.setValue(!!basicConfig.slave && !isEqual(basicConfig.slave, {})); } - validate(): ValidationErrors | null { - return this.basicFormGroup.valid ? null : { - basicFormGroup: {valid: false} - }; + validate(basicFormControl: UntypedFormControl): ValidationErrors | null { + const { master, slave } = basicFormControl.value; + const isEmpty = !master?.slaves?.length && (isEqual(slave, {}) || !slave); + if (!this.basicFormGroup.valid || isEmpty) { + return { + basicFormGroup: {valid: false} + }; + } + return null; } private updateSlaveEnabling(isEnabled: boolean): void { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 5f51f59284..75fc62ed5e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -34,12 +34,8 @@ import { ControlValueAccessor, FormArray, FormBuilder, - NG_VALIDATORS, NG_VALUE_ACCESSOR, - UntypedFormControl, UntypedFormGroup, - ValidationErrors, - Validator, } from '@angular/forms'; import { ModbusMasterConfig, @@ -63,16 +59,11 @@ import { TbTableDatasource } from '@shared/components/table/table-datasource.abs useExisting: forwardRef(() => ModbusMasterTableComponent), multi: true }, - { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => ModbusMasterTableComponent), - multi: true - } ], standalone: true, imports: [CommonModule, SharedModule] }) -export class ModbusMasterTableComponent implements ControlValueAccessor, Validator, AfterViewInit, OnInit, OnDestroy { +export class ModbusMasterTableComponent implements ControlValueAccessor, AfterViewInit, OnInit, OnDestroy { @ViewChild('searchInput') searchInputField: ElementRef; @@ -139,12 +130,6 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat this.pushDataAsFormArrays(master.slaves); } - validate(masterControl: UntypedFormControl): ValidationErrors | null { - return masterControl.parent.get('slave').enabled || this.slaves.controls.length ? null : { - slavesFormGroup: {valid: false} - }; - } - enterFilterMode(): void { this.textSearchMode = true; this.cdr.detectChanges(); From a0656dc5b842258cbc55182b2f8ea90db234de06 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 1 Aug 2024 12:58:00 +0300 Subject: [PATCH 20/29] refactoring --- .../modbus/modbus-basic-config/modbus-basic-config.component.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 3ed0ebf124..015fc97f1b 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -95,7 +95,6 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat .subscribe(enable => { this.updateSlaveEnabling(enable); this.basicFormGroup.get('slave').updateValueAndValidity({emitEvent: !!this.onChange}); - this.basicFormGroup.get('master').updateValueAndValidity({emitEvent: !!this.onChange}); }); } From d203d819f8b2c73d8634c62e1ab13468e8514360 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Thu, 1 Aug 2024 15:28:49 +0300 Subject: [PATCH 21/29] small typing adjustment --- .../modbus-master-table/modbus-master-table.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts index 14f3635b98..b3d316be23 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-master-table/modbus-master-table.component.ts @@ -43,6 +43,8 @@ import { import { ModbusMasterConfig, ModbusProtocolLabelsMap, + ModbusSlaveInfo, + ModbusValues, SlaveConfig } from '@home/components/widget/lib/gateway/gateway-widget.models'; import { isDefinedAndNotNull, isUndefinedOrNull } from '@core/utils'; @@ -164,7 +166,7 @@ export class ModbusMasterTableComponent implements ControlValueAccessor, Validat } const withIndex = isDefinedAndNotNull(index); const value = withIndex ? this.slaves.at(index).value : {}; - this.dialog.open(ModbusSlaveDialogComponent, { + this.dialog.open(ModbusSlaveDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { From 779cfea5ca26481a9c2b8be2aba40029c3ba6ce9 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 2 Aug 2024 17:16:37 +0300 Subject: [PATCH 22/29] Added gateway connectors synced save adjustments --- .../mqtt-basic-config.component.ts | 18 ++++++++-- .../gateway/gateway-connectors.component.ts | 33 ++++++++----------- .../lib/gateway/gateway-widget.models.ts | 2 +- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts index 8ae9fc6163..a70bf956a2 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts @@ -84,7 +84,7 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator mappingTypes = MappingType; basicFormGroup: FormGroup; - private onChange: (value: string) => void; + private onChange: (value: MQTTBasicConfig) => void; private onTouched: () => void; private destroy$ = new Subject(); @@ -100,7 +100,7 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) .subscribe(value => { - this.onChange(value); + this.onChange(this.getMappedMQTTConfig(value)); this.onTouched(); }); } @@ -110,7 +110,7 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator this.destroy$.complete(); } - registerOnChange(fn: (value: string) => void): void { + registerOnChange(fn: (value: MQTTBasicConfig) => void): void { this.onChange = fn; } @@ -135,6 +135,18 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator this.basicFormGroup.setValue(editedBase, {emitEvent: false}); } + private getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig { + const { broker, workers, dataMapping, requestsMapping } = basicConfig || {}; + return workers ? { + dataMapping, + requestsMapping, + broker: { + ...broker, + ...workers, + } + } : basicConfig; + } + validate(): ValidationErrors | null { return this.basicFormGroup.valid ? null : { basicFormGroup: {valid: false} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index e4c5360cdf..ebe5ebd646 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -60,7 +60,7 @@ import { } from './gateway-widget.models'; import { MatDialog } from '@angular/material/dialog'; import { AddConnectorDialogComponent } from '@home/components/widget/lib/gateway/dialog/add-connector-dialog.component'; -import { debounceTime, take, takeUntil, tap } from 'rxjs/operators'; +import { debounceTime, filter, take, takeUntil, tap } from 'rxjs/operators'; import { ErrorStateMatcher } from '@angular/material/core'; import { PageData } from '@shared/models/page/page-data'; @@ -133,6 +133,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie private basicConfigSub: Subscription; + private connectorUpdateInProgress = false; + private subscriptionOptions: WidgetSubscriptionOptions = { callbacks: { onDataUpdated: () => this.ctx.ngZone.run(() => { @@ -210,6 +212,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }); this.connectorForm.get('configurationJson').valueChanges.pipe( + filter(() => !this.connectorUpdateInProgress), takeUntil(this.destroy$) ).subscribe((config) => { const basicConfig = this.connectorForm.get('basicConfig'); @@ -275,7 +278,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } saveConnector(): void { - const value = this.connectorForm.get('type').value === ConnectorType.MQTT ? this.getMappedMQTTValue() : this.connectorForm.value; + const value = { ...this.connectorForm.value }; value.configuration = camelCase(value.name) + '.json'; delete value.basicConfig; if (value.type !== ConnectorType.GRPC) { @@ -336,20 +339,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }); } - private getMappedMQTTValue(): GatewayConnector { - const value = this.connectorForm.value; - return { - ...value, - configurationJson: { - ...value.configurationJson, - broker: { - ...value.configurationJson.broker, - ...value.configurationJson.workers, - } - } - }; - } - private updateData(reload: boolean = false): void { this.pageLink.sortOrder.property = this.sort.active; this.pageLink.sortOrder.direction = Direction[this.sort.direction.toUpperCase()]; @@ -383,7 +372,9 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } const sharedIndex = this.sharedAttributeData.findIndex(data => { const sharedData = data.value; - return sharedData.name === connectorData.name && sharedData.ts && sharedData.ts <= connectorData.ts; + return sharedData.name === connectorData.name + && sharedData.ts && sharedData.ts <= connectorData.ts + && isEqual(sharedData.value, connectorData.value); }); return sharedIndex !== -1; } @@ -684,6 +675,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie this.basicConfigSub.unsubscribe(); } this.basicConfigSub = this.connectorForm.get('basicConfig').valueChanges.pipe( + filter(() => !this.connectorUpdateInProgress), takeUntil(this.destroy$) ).subscribe((config) => { const configJson = this.connectorForm.get('configurationJson'); @@ -734,13 +726,16 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie case ConnectorType.MQTT: case ConnectorType.OPCUA: case ConnectorType.MODBUS: - this.connectorForm.get('type').patchValue(connector.type, {emitValue: false, onlySelf: true}); - this.connectorForm.get('basicConfig').setValue({}, {emitEvent: false}); + this.connectorUpdateInProgress = true; + if (connector.name !== this.connectorForm.value.name) { + this.connectorForm.get('basicConfig').setValue({}, {emitEvent: false}); + } setTimeout(() => { this.connectorForm.patchValue({...connector, mode: connector.mode || ConnectorConfigurationModes.BASIC}); this.createBasicConfigWatcher(); this.connectorForm.markAsPristine(); + this.connectorUpdateInProgress = false; }); break; default: diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 8df3994ea2..7878296039 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -182,7 +182,7 @@ export interface MQTTBasicConfig { dataMapping: ConverterConnectorMapping[]; requestsMapping: Record | RequestMappingData[]; broker: BrokerConfig; - workers: WorkersConfig; + workers?: WorkersConfig; } export interface OPCBasicConfig { From 9a239f2c2e132a82db18a7e5e4b459c6d6719047 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 2 Aug 2024 17:51:13 +0300 Subject: [PATCH 23/29] isCisConnectorSynced adjustments --- .../widget/lib/gateway/gateway-connectors.component.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index ebe5ebd646..0434e9e853 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -372,9 +372,11 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } const sharedIndex = this.sharedAttributeData.findIndex(data => { const sharedData = data.value; - return sharedData.name === connectorData.name - && sharedData.ts && sharedData.ts <= connectorData.ts - && isEqual(sharedData.value, connectorData.value); + const hasSameName = sharedData.name === connectorData.name; + const hasEmptyConfig = isEqual(sharedData.configurationJson, {}) && hasSameName; + const hasSameConfig =isEqual(sharedData.configurationJson, connectorData.configurationJson); + const isRecentlyCreated = sharedData.ts && sharedData.ts <= connectorData.ts; + return hasSameName && isRecentlyCreated && (hasSameConfig || hasEmptyConfig); }); return sharedIndex !== -1; } From 4bbfb09ab41929fa6f07a06b8c143163da03ec84 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Fri, 2 Aug 2024 18:34:23 +0300 Subject: [PATCH 24/29] shared directives adjustments --- ui-ngx/src/app/modules/common/modules-map.ts | 6 ++++++ ui-ngx/src/app/shared/directives/public-api.ts | 2 ++ .../shared/directives/truncate-with-tooltip.directive.ts | 2 -- ui-ngx/src/app/shared/public-api.ts | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 ui-ngx/src/app/shared/directives/public-api.ts diff --git a/ui-ngx/src/app/modules/common/modules-map.ts b/ui-ngx/src/app/modules/common/modules-map.ts index fcb4e0b411..c06863c6e8 100644 --- a/ui-ngx/src/app/modules/common/modules-map.ts +++ b/ui-ngx/src/app/modules/common/modules-map.ts @@ -99,6 +99,9 @@ import * as TbJsonPipe from '@shared/pipe/tbJson.pipe'; import * as TruncatePipe from '@shared/pipe/truncate.pipe'; import * as ImagePipe from '@shared/pipe/image.pipe'; +import * as EllipsisChipListDirective from '@shared/directives/ellipsis-chip-list.directive'; +import * as TruncateWithTooltipDirective from '@shared/directives/truncate-with-tooltip.directive'; + import * as coercion from '@shared/decorators/coercion'; import * as enumerable from '@shared/decorators/enumerable'; import * as TbInject from '@shared/decorators/tb-inject'; @@ -422,6 +425,9 @@ class ModulesMap implements IModulesMap { '@shared/pipe/truncate.pipe': TruncatePipe, '@shared/pipe/image.pipe': ImagePipe, + '@shared/directives/ellipsis-chip-list.directive': EllipsisChipListDirective, + '@shared/directives/truncate-with-tooltip.directive': TruncateWithTooltipDirective, + '@shared/decorators/coercion': coercion, '@shared/decorators/enumerable': enumerable, '@shared/decorators/tb-inject': TbInject, diff --git a/ui-ngx/src/app/shared/directives/public-api.ts b/ui-ngx/src/app/shared/directives/public-api.ts new file mode 100644 index 0000000000..08431abb28 --- /dev/null +++ b/ui-ngx/src/app/shared/directives/public-api.ts @@ -0,0 +1,2 @@ +export * from './truncate-with-tooltip.directive'; +export * from './ellipsis-chip-list.directive'; diff --git a/ui-ngx/src/app/shared/directives/truncate-with-tooltip.directive.ts b/ui-ngx/src/app/shared/directives/truncate-with-tooltip.directive.ts index 1281b86040..ad4e4cbbc1 100644 --- a/ui-ngx/src/app/shared/directives/truncate-with-tooltip.directive.ts +++ b/ui-ngx/src/app/shared/directives/truncate-with-tooltip.directive.ts @@ -105,8 +105,6 @@ export class TruncateWithTooltipDirective implements OnInit, AfterViewInit, OnDe private showTooltip(): void { this.tooltip.message = this.text; - - this.renderer.setAttribute(this.elementRef.nativeElement, 'matTooltip', this.text); this.tooltip.show(); } diff --git a/ui-ngx/src/app/shared/public-api.ts b/ui-ngx/src/app/shared/public-api.ts index bd3d565da3..1f38b7f70c 100644 --- a/ui-ngx/src/app/shared/public-api.ts +++ b/ui-ngx/src/app/shared/public-api.ts @@ -19,3 +19,4 @@ export * from './decorators/public-api'; export * from './models/public-api'; export * from './pipe/public-api'; export * from './shared.module'; +export * from './directives/public-api'; From 4e71093aca9073e5eeae091240a2a0520b1dfdad Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 5 Aug 2024 13:05:07 +0300 Subject: [PATCH 25/29] changed connector update approach --- .../mqtt-basic-config.component.ts | 38 +++++++++--- .../gateway/gateway-connectors.component.ts | 60 ++++++++++++------- .../lib/gateway/gateway-widget.models.ts | 11 +++- 3 files changed, 76 insertions(+), 33 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts index a70bf956a2..f70139eb1e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts @@ -47,6 +47,7 @@ import { import { MappingTableComponent } from '@home/components/widget/lib/gateway/connectors-configuration/mapping-table/mapping-table.component'; +import { isDefinedAndNotNull } from '@core/utils'; @Component({ selector: 'tb-mqtt-basic-config', @@ -136,15 +137,20 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator } private getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig { - const { broker, workers, dataMapping, requestsMapping } = basicConfig || {}; - return workers ? { - dataMapping, - requestsMapping, - broker: { + let { broker, workers, dataMapping, requestsMapping } = basicConfig || {}; + + if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) { + broker = { ...broker, ...workers, - } - } : basicConfig; + }; + } + + if ((requestsMapping as RequestMappingData[])?.length) { + requestsMapping = this.getRequestDataObject(requestsMapping as RequestMappingData[]); + } + + return { broker, workers, dataMapping, requestsMapping }; } validate(): ValidationErrors | null { @@ -153,7 +159,7 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator }; } - private getRequestDataArray(value: Record): RequestMappingData[] { + private getRequestDataArray(value: Record): RequestMappingData[] { const mappingConfigs = []; if (isObject(value)) { @@ -169,4 +175,20 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator return mappingConfigs; } + + private getRequestDataObject(array: RequestMappingData[]): Record { + const result = { + connectRequests: [], + disconnectRequests: [], + attributeRequests: [], + attributeUpdates: [], + serverSideRpc: [], + }; + + array.forEach(({ requestType, requestValue }) => { + result[requestType].push(requestValue); + }); + + return result as Record; + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts index 0434e9e853..a91a7c1b9f 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-connectors.component.ts @@ -51,6 +51,7 @@ import { EntityType } from '@shared/models/entity-type.models'; import { AddConnectorConfigData, ConnectorBaseConfig, + ConnectorBaseInfo, ConnectorConfigurationModes, ConnectorType, GatewayConnector, @@ -133,7 +134,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie private basicConfigSub: Subscription; - private connectorUpdateInProgress = false; + private jsonConfigSub: Subscription; private subscriptionOptions: WidgetSubscriptionOptions = { callbacks: { @@ -211,18 +212,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie } }); - this.connectorForm.get('configurationJson').valueChanges.pipe( - filter(() => !this.connectorUpdateInProgress), - takeUntil(this.destroy$) - ).subscribe((config) => { - const basicConfig = this.connectorForm.get('basicConfig'); - const type = this.connectorForm.get('type').value; - const mode = this.connectorForm.get('mode').value; - if (!isEqual(config, basicConfig?.value) && this.allowBasicConfig.has(type) && mode === ConnectorConfigurationModes.ADVANCED) { - this.connectorForm.get('basicConfig').patchValue(config, {emitEvent: false}); - } - }); - this.dataSource.sort = this.sort; this.dataSource.sortingDataAccessor = (data: AttributeData, sortHeaderId: string) => { switch (sortHeaderId) { @@ -374,13 +363,26 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie const sharedData = data.value; const hasSameName = sharedData.name === connectorData.name; const hasEmptyConfig = isEqual(sharedData.configurationJson, {}) && hasSameName; - const hasSameConfig =isEqual(sharedData.configurationJson, connectorData.configurationJson); + const hasSameConfig = this.hasSameConfig(sharedData.configurationJson, connectorData.configurationJson); const isRecentlyCreated = sharedData.ts && sharedData.ts <= connectorData.ts; return hasSameName && isRecentlyCreated && (hasSameConfig || hasEmptyConfig); }); return sharedIndex !== -1; } + private hasSameConfig(sharedDataConfigJson: ConnectorBaseInfo, connectorDataConfigJson: ConnectorBaseInfo): boolean { + const { name, id, enableRemoteLogging, logLevel, ...sharedDataConfig } = sharedDataConfigJson; + const { + name: connectorName, + id: connectorId, + enableRemoteLogging: connectorEnableRemoteLogging, + logLevel: connectorLogLevel, + ...connectorConfig + } = connectorDataConfigJson; + + return isEqual(sharedDataConfig, connectorConfig); + } + private combineData(): void { this.dataSource.data = [...this.activeData, ...this.inactiveData, ...this.sharedAttributeData].filter((item, index, self) => index === self.findIndex((t) => t.key === item.key) @@ -677,7 +679,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie this.basicConfigSub.unsubscribe(); } this.basicConfigSub = this.connectorForm.get('basicConfig').valueChanges.pipe( - filter(() => !this.connectorUpdateInProgress), + filter(() => !!this.initialConnector), takeUntil(this.destroy$) ).subscribe((config) => { const configJson = this.connectorForm.get('configurationJson'); @@ -690,6 +692,22 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie }); } + private createJsonConfigWatcher(): void { + if (this.jsonConfigSub) { + this.jsonConfigSub.unsubscribe(); + } + this.jsonConfigSub = this.connectorForm.get('configurationJson').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((config) => { + const basicConfig = this.connectorForm.get('basicConfig'); + const type = this.connectorForm.get('type').value; + const mode = this.connectorForm.get('mode').value; + if (!isEqual(config, basicConfig?.value) && this.allowBasicConfig.has(type) && mode === ConnectorConfigurationModes.ADVANCED) { + this.connectorForm.get('basicConfig').patchValue(config, {emitEvent: false}); + } + }); + } + private confirmConnectorChange(): Observable { if (this.initialConnector && this.connectorForm.dirty) { return this.dialogService.confirm( @@ -728,22 +746,18 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie case ConnectorType.MQTT: case ConnectorType.OPCUA: case ConnectorType.MODBUS: - this.connectorUpdateInProgress = true; - if (connector.name !== this.connectorForm.value.name) { - this.connectorForm.get('basicConfig').setValue({}, {emitEvent: false}); - } - + this.connectorForm.get('mode').setValue(connector.mode || ConnectorConfigurationModes.BASIC, {emitEvent: false}); setTimeout(() => { - this.connectorForm.patchValue({...connector, mode: connector.mode || ConnectorConfigurationModes.BASIC}); - this.createBasicConfigWatcher(); + this.connectorForm.patchValue(connector, {emitEvent: false}); this.connectorForm.markAsPristine(); - this.connectorUpdateInProgress = false; + this.createBasicConfigWatcher(); }); break; default: this.connectorForm.patchValue({...connector, mode: null}); this.connectorForm.markAsPristine(); } + this.createJsonConfigWatcher(); } private setClientData(data: PageData): void { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts index 7878296039..22915ad9eb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/gateway-widget.models.ts @@ -176,11 +176,18 @@ export type ConnectorMapping = DeviceConnectorMapping | RequestMappingData | Con export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingFormValue | ConverterMappingFormValue; -export type ConnectorBaseConfig = MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig; +export type ConnectorBaseConfig = ConnectorBaseInfo | MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig; + +export interface ConnectorBaseInfo { + name: string; + id: string; + enableRemoteLogging: boolean; + logLevel: GatewayLogLevel; +} export interface MQTTBasicConfig { dataMapping: ConverterConnectorMapping[]; - requestsMapping: Record | RequestMappingData[]; + requestsMapping: Record | RequestMappingData[]; broker: BrokerConfig; workers?: WorkersConfig; } From 915929f79320a32c93f6095690f8d3146eb1f838 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 5 Aug 2024 14:24:34 +0300 Subject: [PATCH 26/29] refactoring --- .../mqtt-basic-config/mqtt-basic-config.component.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts index f70139eb1e..25f8671201 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/mqtt-basic-config/mqtt-basic-config.component.ts @@ -177,18 +177,15 @@ export class MqttBasicConfigComponent implements ControlValueAccessor, Validator } private getRequestDataObject(array: RequestMappingData[]): Record { - const result = { + return array.reduce((result, { requestType, requestValue }) => { + result[requestType].push(requestValue); + return result; + }, { connectRequests: [], disconnectRequests: [], attributeRequests: [], attributeUpdates: [], serverSideRpc: [], - }; - - array.forEach(({ requestType, requestValue }) => { - result[requestType].push(requestValue); }); - - return result as Record; } } From 1e89a62d3fce69fcb0714104beef7da89fdc8843 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 5 Aug 2024 14:42:59 +0300 Subject: [PATCH 27/29] format headers --- ui-ngx/src/app/shared/directives/public-api.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ui-ngx/src/app/shared/directives/public-api.ts b/ui-ngx/src/app/shared/directives/public-api.ts index 08431abb28..6f25320d90 100644 --- a/ui-ngx/src/app/shared/directives/public-api.ts +++ b/ui-ngx/src/app/shared/directives/public-api.ts @@ -1,2 +1,18 @@ +/// +/// Copyright © 2016-2024 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. +/// + export * from './truncate-with-tooltip.directive'; export * from './ellipsis-chip-list.directive'; From 7dd9e47065acf1710cd55ed8b8d626a91d178c6f Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 6 Aug 2024 15:13:18 +0300 Subject: [PATCH 28/29] minor fixes --- .../modbus-data-keys-panel.component.scss | 2 +- .../modbus-slave-config.component.html | 2 +- .../modbus-slave-config.component.ts | 4 ++-- .../modbus-slave-dialog.component.html | 8 ++++---- .../modbus-slave-dialog.component.ts | 10 +++++----- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss index d9ef45d66b..445ac6c0ae 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-data-keys-panel/modbus-data-keys-panel.component.scss @@ -20,7 +20,7 @@ max-width: 700px; .title-container { - width: 12vw; + width: 180px; } .key-panel { diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html index d37c8cc9ee..12ddb479ca 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.html @@ -161,7 +161,7 @@
-
gateway.poll-period
+
gateway.poll-period
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts index 2a8488a2d4..d0e8ecdd4e 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-config/modbus-slave-config.component.ts @@ -106,11 +106,11 @@ 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: [0, [Validators.required]], + unitId: [null, [Validators.required]], baudrate: [this.modbusBaudrates[0]], deviceName: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], deviceType: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex)]], - pollPeriod: [5000], + pollPeriod: [5000, [Validators.required]], sendDataToThingsBoard: [false], byteOrder:[ModbusOrderType.BIG], security: [], diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html index c7fb50f146..088b385623 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.html @@ -306,7 +306,7 @@
-
gateway.poll-period
+
gateway.poll-period
@@ -314,7 +314,7 @@
-
gateway.connect-attempt-time
+
gateway.connect-attempt-time
@@ -322,7 +322,7 @@
-
gateway.connect-attempt-count
+
gateway.connect-attempt-count
@@ -330,7 +330,7 @@
-
gateway.wait-after-failed-attempts
+
gateway.wait-after-failed-attempts
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts index a00a488aa0..e21a9921a7 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-slave-dialog/modbus-slave-dialog.component.ts @@ -163,7 +163,7 @@ export class ModbusSlaveDialogComponent extends DialogComponent Date: Tue, 6 Aug 2024 16:47:35 +0300 Subject: [PATCH 29/29] disable slave fix --- .../modbus-basic-config/modbus-basic-config.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts index 1fca768980..3aadc74fbd 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-basic-config/modbus-basic-config.component.ts @@ -80,8 +80,8 @@ export class ModbusBasicConfigComponent implements ControlValueAccessor, Validat this.basicFormGroup.valueChanges .pipe(takeUntil(this.destroy$)) - .subscribe(value => { - this.onChange(value); + .subscribe(({ master, slave }) => { + this.onChange({ master, slave: slave ?? {} }); this.onTouched(); }); }