Modbus fixes and adjustments

This commit is contained in:
mpetrov 2024-09-12 13:49:48 +03:00
parent bcdf0393a3
commit a8380f18e0
15 changed files with 68 additions and 20 deletions

View File

@ -20,7 +20,6 @@ import {
ModbusBasicConfig_v3_5_2, ModbusBasicConfig_v3_5_2,
ModbusLegacyBasicConfig, ModbusLegacyBasicConfig,
ModbusLegacySlave, ModbusLegacySlave,
ModbusMasterConfig,
ModbusSlave, ModbusSlave,
} from '../gateway-widget.models'; } from '../gateway-widget.models';
import { GatewayConnectorVersionProcessor } from './gateway-connector-version-processor.abstract'; import { GatewayConnectorVersionProcessor } from './gateway-connector-version-processor.abstract';
@ -40,9 +39,9 @@ export class ModbusVersionProcessor extends GatewayConnectorVersionProcessor<any
return { return {
...this.connector, ...this.connector,
configurationJson: { configurationJson: {
master: configurationJson.master master: configurationJson.master?.slaves
? ModbusVersionMappingUtil.mapMasterToUpgradedVersion(configurationJson.master) ? ModbusVersionMappingUtil.mapMasterToUpgradedVersion(configurationJson.master)
: {} as ModbusMasterConfig, : { slaves: [] },
slave: configurationJson.slave slave: configurationJson.slave
? ModbusVersionMappingUtil.mapSlaveToUpgradedVersion(configurationJson.slave as ModbusLegacySlave) ? ModbusVersionMappingUtil.mapSlaveToUpgradedVersion(configurationJson.slave as ModbusLegacySlave)
: {} as ModbusSlave, : {} as ModbusSlave,

View File

@ -62,11 +62,6 @@ export abstract class ModbusBasicConfigDirective<BasicConfig>
}); });
} }
protected override onBasicFormGroupChange(value: ModbusBasicConfig_v3_5_2): void {
super.onBasicFormGroupChange(value);
this.basicFormGroup.get('slave').updateValueAndValidity({ emitEvent: !!this.onChange });
}
private updateSlaveEnabling(isEnabled: boolean): void { private updateSlaveEnabling(isEnabled: boolean): void {
if (isEnabled) { if (isEnabled) {
this.basicFormGroup.get('slave').enable({ emitEvent: false }); this.basicFormGroup.get('slave').enable({ emitEvent: false });

View File

@ -58,10 +58,10 @@ import {
}) })
export class ModbusBasicConfigComponent extends ModbusBasicConfigDirective<ModbusBasicConfig_v3_5_2> { export class ModbusBasicConfigComponent extends ModbusBasicConfigDirective<ModbusBasicConfig_v3_5_2> {
protected override mapConfigToFormValue(config: ModbusBasicConfig_v3_5_2): ModbusBasicConfig_v3_5_2 { protected override mapConfigToFormValue({ master, slave }: ModbusBasicConfig_v3_5_2): ModbusBasicConfig_v3_5_2 {
return { return {
master: config.master ?? {} as ModbusMasterConfig, master: master?.slaves ? master : { slaves: [] } as ModbusMasterConfig,
slave: config.slave ?? {} as ModbusSlave, slave: slave ?? {} as ModbusSlave,
}; };
} }

View File

@ -62,7 +62,9 @@ export class ModbusLegacyBasicConfigComponent extends ModbusBasicConfigDirective
protected override mapConfigToFormValue(config: ModbusLegacyBasicConfig): ModbusBasicConfig_v3_5_2 { protected override mapConfigToFormValue(config: ModbusLegacyBasicConfig): ModbusBasicConfig_v3_5_2 {
return { return {
master: config.master ? ModbusVersionMappingUtil.mapMasterToUpgradedVersion(config.master) : {} as ModbusMasterConfig, master: config.master?.slaves
? ModbusVersionMappingUtil.mapMasterToUpgradedVersion(config.master)
: { slaves: [] } as ModbusMasterConfig,
slave: config.slave ? ModbusVersionMappingUtil.mapSlaveToUpgradedVersion(config.slave) : {} as ModbusSlave, slave: config.slave ? ModbusVersionMappingUtil.mapSlaveToUpgradedVersion(config.slave) : {} as ModbusSlave,
}; };
} }

View File

@ -31,9 +31,15 @@
</div> </div>
<ng-template #tagName> <ng-template #tagName>
<div class="tb-flex"> <div class="tb-flex">
<div class="title-container" tbTruncateWithTooltip>{{ 'gateway.key' | translate }}: {{ keyControl.get('tag').value }}</div> <div class="title-container tb-flex">{{ 'gateway.key' | translate }}:
<div class="title-container">{{ 'gateway.address' | translate }}: {{ keyControl.get('address').value }}</div> <span class="key-label" tbTruncateWithTooltip>{{ keyControl.get('tag').value }}</span>
<div class="title-container">{{ 'gateway.type' | translate }}: {{ keyControl.get('type').value }}</div> </div>
<div class="title-container">{{ 'gateway.address' | translate }}:
<span class="key-label">{{ keyControl.get('address').value }}</span>
</div>
<div class="title-container">{{ 'gateway.type' | translate }}:
<span class="key-label">{{ keyControl.get('type').value }}</span>
</div>
</div> </div>
</ng-template> </ng-template>
</mat-panel-title> </mat-panel-title>

View File

@ -23,6 +23,10 @@
width: 180px; width: 180px;
} }
.key-label {
font-weight: 400;
}
.key-panel { .key-panel {
height: 500px; height: 500px;
overflow: auto; overflow: auto;

View File

@ -197,6 +197,16 @@
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
<div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{ 'gateway.hints.modbus.word-order' | translate }}" translate>gateway.word-order</div>
<div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">
<mat-select formControlName="wordOrder">
<mat-option *ngFor="let order of modbusOrderType" [value]="order">{{ order }}</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
<div *ngIf="protocolType !== ModbusProtocolType.Serial" class="tb-form-panel stroked tb-slide-toggle"> <div *ngIf="protocolType !== ModbusProtocolType.Serial" class="tb-form-panel stroked tb-slide-toggle">
<mat-expansion-panel class="tb-settings" [expanded]="showSecurityControl.value"> <mat-expansion-panel class="tb-settings" [expanded]="showSecurityControl.value">
<mat-expansion-panel-header fxLayout="row wrap"> <mat-expansion-panel-header fxLayout="row wrap">

View File

@ -113,6 +113,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat
pollPeriod: [5000, [Validators.required]], pollPeriod: [5000, [Validators.required]],
sendDataToThingsBoard: [false], sendDataToThingsBoard: [false],
byteOrder:[ModbusOrderType.BIG], byteOrder:[ModbusOrderType.BIG],
wordOrder: [ModbusOrderType.BIG],
security: [], security: [],
identity: this.fb.group({ identity: this.fb.group({
vendorName: ['', [Validators.pattern(noLeadTrailSpacesRegex)]], vendorName: ['', [Validators.pattern(noLeadTrailSpacesRegex)]],
@ -243,6 +244,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat
pollPeriod = 5000, pollPeriod = 5000,
sendDataToThingsBoard = false, sendDataToThingsBoard = false,
byteOrder = ModbusOrderType.BIG, byteOrder = ModbusOrderType.BIG,
wordOrder = ModbusOrderType.BIG,
security = {}, security = {},
identity = { identity = {
vendorName: '', vendorName: '',
@ -266,6 +268,7 @@ export class ModbusSlaveConfigComponent implements ControlValueAccessor, Validat
pollPeriod, pollPeriod,
sendDataToThingsBoard: !!sendDataToThingsBoard, sendDataToThingsBoard: !!sendDataToThingsBoard,
byteOrder, byteOrder,
wordOrder,
security, security,
identity, identity,
values, values,

View File

@ -260,7 +260,7 @@
</mat-form-field> </mat-form-field>
</div> </div>
</div> </div>
<div *ngIf="protocolType !== ModbusProtocolType.Serial" class="tb-form-row column-xs" fxLayoutAlign="space-between center"> <div class="tb-form-row column-xs" fxLayoutAlign="space-between center">
<div class="fixed-title-width" tb-hint-tooltip-icon="{{ 'gateway.hints.modbus.word-order' | translate }}" translate>gateway.word-order</div> <div class="fixed-title-width" tb-hint-tooltip-icon="{{ 'gateway.hints.modbus.word-order' | translate }}" translate>gateway.word-order</div>
<div class="tb-flex no-gap"> <div class="tb-flex no-gap">
<mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic"> <mat-form-field class="tb-flex no-gap" appearance="outline" subscriptSizing="dynamic">

View File

@ -101,7 +101,7 @@ export class ModbusSlaveDialogComponent extends DialogComponent<ModbusSlaveDialo
helpBaseUrl + '/docs/iot-gateway/config/modbus/#section-master-description-and-configuration-parameters'; helpBaseUrl + '/docs/iot-gateway/config/modbus/#section-master-description-and-configuration-parameters';
private readonly serialSpecificControlKeys = ['serialPort', 'baudrate', 'stopbits', 'bytesize', 'parity', 'strict']; private readonly serialSpecificControlKeys = ['serialPort', 'baudrate', 'stopbits', 'bytesize', 'parity', 'strict'];
private readonly tcpUdpSpecificControlKeys = ['port', 'security', 'host', 'wordOrder']; private readonly tcpUdpSpecificControlKeys = ['port', 'security', 'host'];
private destroy$ = new Subject<void>(); private destroy$ = new Subject<void>();

View File

@ -48,6 +48,8 @@
mat-icon-button mat-icon-button
color="primary" color="primary"
[disabled]="disabled" [disabled]="disabled"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#attributesButton #attributesButton
(click)="manageKeys($event, attributesButton, ModbusValueKey.ATTRIBUTES, register)"> (click)="manageKeys($event, attributesButton, ModbusValueKey.ATTRIBUTES, register)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -69,6 +71,8 @@
mat-icon-button mat-icon-button
color="primary" color="primary"
[disabled]="disabled" [disabled]="disabled"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#telemetryButton #telemetryButton
(click)="manageKeys($event, telemetryButton, ModbusValueKey.TIMESERIES, register)"> (click)="manageKeys($event, telemetryButton, ModbusValueKey.TIMESERIES, register)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -90,6 +94,8 @@
mat-icon-button mat-icon-button
[disabled]="disabled" [disabled]="disabled"
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#attributesUpdatesButton #attributesUpdatesButton
(click)="manageKeys($event, attributesUpdatesButton, ModbusValueKey.ATTRIBUTES_UPDATES, register)"> (click)="manageKeys($event, attributesUpdatesButton, ModbusValueKey.ATTRIBUTES_UPDATES, register)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -111,6 +117,8 @@
mat-icon-button mat-icon-button
color="primary" color="primary"
[disabled]="disabled" [disabled]="disabled"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#rpcRequestsButton #rpcRequestsButton
(click)="manageKeys($event, rpcRequestsButton, ModbusValueKey.RPC_REQUESTS, register)"> (click)="manageKeys($event, rpcRequestsButton, ModbusValueKey.RPC_REQUESTS, register)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>

View File

@ -110,6 +110,8 @@
<button type="button" <button type="button"
mat-icon-button mat-icon-button
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#attributesButton #attributesButton
(click)="manageKeys($event, attributesButton, MappingKeysType.ATTRIBUTES)"> (click)="manageKeys($event, attributesButton, MappingKeysType.ATTRIBUTES)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -130,6 +132,8 @@
<button type="button" <button type="button"
mat-icon-button mat-icon-button
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#telemetryButton #telemetryButton
(click)="manageKeys($event, telemetryButton, MappingKeysType.TIMESERIES)"> (click)="manageKeys($event, telemetryButton, MappingKeysType.TIMESERIES)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -175,6 +179,8 @@
<button type="button" <button type="button"
mat-icon-button mat-icon-button
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#keysButton #keysButton
(click)="manageKeys($event, keysButton, MappingKeysType.CUSTOM)"> (click)="manageKeys($event, keysButton, MappingKeysType.CUSTOM)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -666,6 +672,8 @@
<button type="button" <button type="button"
mat-icon-button mat-icon-button
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#opcAttributesButton #opcAttributesButton
(click)="manageKeys($event, opcAttributesButton, MappingKeysType.ATTRIBUTES)"> (click)="manageKeys($event, opcAttributesButton, MappingKeysType.ATTRIBUTES)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -686,6 +694,8 @@
<button type="button" <button type="button"
mat-icon-button mat-icon-button
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#opcTelemetryButton #opcTelemetryButton
(click)="manageKeys($event, opcTelemetryButton, MappingKeysType.TIMESERIES)"> (click)="manageKeys($event, opcTelemetryButton, MappingKeysType.TIMESERIES)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -706,6 +716,8 @@
<button type="button" <button type="button"
mat-icon-button mat-icon-button
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#attributesUpdatesButton #attributesUpdatesButton
(click)="manageKeys($event, attributesUpdatesButton, MappingKeysType.ATTRIBUTES_UPDATES)"> (click)="manageKeys($event, attributesUpdatesButton, MappingKeysType.ATTRIBUTES_UPDATES)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>
@ -726,6 +738,8 @@
<button type="button" <button type="button"
mat-icon-button mat-icon-button
color="primary" color="primary"
matTooltip="{{ 'action.edit' | translate }}"
matTooltipPosition="above"
#rpcMethodsButton #rpcMethodsButton
(click)="manageKeys($event, rpcMethodsButton, MappingKeysType.RPC_METHODS)"> (click)="manageKeys($event, rpcMethodsButton, MappingKeysType.RPC_METHODS)">
<tb-icon matButtonIcon>edit</tb-icon> <tb-icon matButtonIcon>edit</tb-icon>

View File

@ -778,7 +778,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
JSON.parse(clientConnectorData.value) : clientConnectorData.value; JSON.parse(clientConnectorData.value) : clientConnectorData.value;
if (this.isConnectorSynced(clientConnectorData) && clientConnectorData.value.configurationJson) { if (this.isConnectorSynced(clientConnectorData) && clientConnectorData.value.configurationJson) {
this.setFormValue(clientConnectorData.value); this.setFormValue({...clientConnectorData.value, mode: this.connectorForm.get('mode').value ?? clientConnectorData.value.mode});
} }
} }
} }

View File

@ -1163,14 +1163,15 @@ export interface ModbusSlave {
pollPeriod: number; pollPeriod: number;
sendDataToThingsBoard: boolean; sendDataToThingsBoard: boolean;
byteOrder: ModbusOrderType; byteOrder: ModbusOrderType;
wordOrder: ModbusOrderType;
identity: ModbusIdentity; identity: ModbusIdentity;
values: ModbusValuesState; values?: ModbusValuesState;
port: string | number; port: string | number;
security: ModbusSecurity; security: ModbusSecurity;
} }
export interface ModbusLegacySlave extends Omit<ModbusSlave, 'values'> { export interface ModbusLegacySlave extends Omit<ModbusSlave, 'values'> {
values: ModbusLegacyRegisterValues; values?: ModbusLegacyRegisterValues;
} }
export type ModbusValuesState = ModbusRegisterValues | ModbusValues; export type ModbusValuesState = ModbusRegisterValues | ModbusValues;

View File

@ -38,6 +38,9 @@ export class ModbusVersionMappingUtil {
} }
static mapSlaveToDowngradedVersion(slave: ModbusSlave): ModbusLegacySlave { static mapSlaveToDowngradedVersion(slave: ModbusSlave): ModbusLegacySlave {
if (!slave?.values) {
return slave as Omit<ModbusLegacySlave, 'values'>;
}
const values = Object.keys(slave.values).reduce((acc, valueKey) => { const values = Object.keys(slave.values).reduce((acc, valueKey) => {
acc = { acc = {
...acc, ...acc,
@ -54,6 +57,9 @@ export class ModbusVersionMappingUtil {
} }
static mapSlaveToUpgradedVersion(slave: ModbusLegacySlave): ModbusSlave { static mapSlaveToUpgradedVersion(slave: ModbusLegacySlave): ModbusSlave {
if (!slave?.values) {
return slave as Omit<ModbusSlave, 'values'>;
}
const values = Object.keys(slave.values).reduce((acc, valueKey) => { const values = Object.keys(slave.values).reduce((acc, valueKey) => {
acc = { acc = {
...acc, ...acc,