Gateway fixes
This commit is contained in:
parent
b9604fa4d0
commit
8b5e25d719
@ -223,6 +223,7 @@
|
||||
</div>
|
||||
<tb-report-strategy
|
||||
*ngIf="withReportStrategy"
|
||||
[defaultValue]="ReportStrategyDefaultValue.Key"
|
||||
formControlName="reportStrategy"
|
||||
[isExpansionMode]="true"
|
||||
/>
|
||||
|
||||
@ -28,7 +28,8 @@ import {
|
||||
import { TbPopoverComponent } from '@shared/components/popover.component';
|
||||
import {
|
||||
ModbusDataType,
|
||||
ModbusEditableDataTypes, ModbusFormValue,
|
||||
ModbusEditableDataTypes,
|
||||
ModbusFormValue,
|
||||
ModbusFunctionCodeTranslationsMap,
|
||||
ModbusObjectCountByDataType,
|
||||
ModbusValue,
|
||||
@ -37,6 +38,7 @@ import {
|
||||
ModifierTypesMap,
|
||||
noLeadTrailSpacesRegex,
|
||||
nonZeroFloat,
|
||||
ReportStrategyDefaultValue,
|
||||
} from '@home/components/widget/lib/gateway/gateway-widget.models';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
@ -91,6 +93,7 @@ export class ModbusDataKeysPanelComponent implements OnInit, OnDestroy {
|
||||
readonly ModbusEditableDataTypes = ModbusEditableDataTypes;
|
||||
readonly ModbusFunctionCodeTranslationsMap = ModbusFunctionCodeTranslationsMap;
|
||||
readonly ModifierTypesMap = ModifierTypesMap;
|
||||
readonly ReportStrategyDefaultValue = ReportStrategyDefaultValue;
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
|
||||
@ -62,6 +62,14 @@
|
||||
</mat-toolbar>
|
||||
<div class="table-container">
|
||||
<table mat-table [dataSource]="dataSource">
|
||||
<ng-container [matColumnDef]="'deviceName'">
|
||||
<mat-header-cell *matHeaderCellDef class="table-value-column">
|
||||
<div tbTruncateWithTooltip>{{ 'gateway.device-name' | translate }}</div>
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let slave" class="table-value-column">
|
||||
<div tbTruncateWithTooltip>{{ slave['deviceName'] }}</div>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
<ng-container [matColumnDef]="'info'">
|
||||
<mat-header-cell *matHeaderCellDef class="table-value-column">
|
||||
{{ 'gateway.info' | translate }}
|
||||
@ -80,7 +88,7 @@
|
||||
</ng-container>
|
||||
<ng-container [matColumnDef]="'type'">
|
||||
<mat-header-cell *matHeaderCellDef class="table-value-column">
|
||||
<div tbTruncateWithTooltip>{{ 'gateway.client-communication-type' | translate }}</div>
|
||||
<div>{{ 'gateway.type' | translate }}</div>
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let slave" class="table-value-column">
|
||||
{{ ModbusProtocolLabelsMap.get(slave['type']) }}
|
||||
@ -121,8 +129,8 @@
|
||||
</div>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
<mat-header-row [ngClass]="{'mat-row-select': true}" *matHeaderRowDef="['info', 'unitId', 'type', 'actions']; sticky: true"></mat-header-row>
|
||||
<mat-row *matRowDef="let slave; columns: ['info', 'unitId', 'type', 'actions']"></mat-row>
|
||||
<mat-header-row [ngClass]="{'mat-row-select': true}" *matHeaderRowDef="['deviceName', 'info', 'unitId', 'type', 'actions']; sticky: true"></mat-header-row>
|
||||
<mat-row *matRowDef="let slave; columns: ['deviceName', 'info', 'unitId', 'type', 'actions']"></mat-row>
|
||||
</table>
|
||||
<section [fxShow]="!textSearchMode && (dataSource.isEmpty() | async)" fxLayoutAlign="center center"
|
||||
class="mat-headline-5 tb-absolute-fill tb-add-new">
|
||||
|
||||
@ -35,6 +35,7 @@ import {
|
||||
ModbusSlaveInfo,
|
||||
noLeadTrailSpacesRegex,
|
||||
PortLimits,
|
||||
ReportStrategyDefaultValue,
|
||||
} from '@home/components/widget/lib/gateway/gateway-widget.models';
|
||||
import { Subject } from 'rxjs';
|
||||
import { DialogComponent } from '@shared/components/dialog.component';
|
||||
@ -64,6 +65,7 @@ export abstract class ModbusSlaveDialogAbstract<Component, Config> extends Dialo
|
||||
readonly ModbusParityLabelsMap = ModbusParityLabelsMap;
|
||||
readonly ModbusProtocolLabelsMap = ModbusProtocolLabelsMap;
|
||||
readonly ModbusMethodLabelsMap = ModbusMethodLabelsMap;
|
||||
readonly ReportStrategyDefaultValue = ReportStrategyDefaultValue;
|
||||
readonly modbusHelpLink =
|
||||
helpBaseUrl + '/docs/iot-gateway/config/modbus/#section-master-description-and-configuration-parameters';
|
||||
|
||||
|
||||
@ -218,7 +218,7 @@
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
<ng-template #reportStrategy>
|
||||
<tb-report-strategy formControlName="reportStrategy" [isExpansionMode]="true"/>
|
||||
<tb-report-strategy [defaultValue]="ReportStrategyDefaultValue.Device" formControlName="reportStrategy" [isExpansionMode]="true"/>
|
||||
</ng-template>
|
||||
<div class="tb-form-panel stroked">
|
||||
<mat-expansion-panel class="tb-settings">
|
||||
|
||||
@ -34,6 +34,7 @@ import {
|
||||
} from '@angular/forms';
|
||||
import {
|
||||
ReportStrategyConfig,
|
||||
ReportStrategyDefaultValue,
|
||||
ReportStrategyType,
|
||||
ReportStrategyTypeTranslationsMap
|
||||
} from '@home/components/widget/lib/gateway/gateway-widget.models';
|
||||
@ -43,7 +44,7 @@ import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
ModbusSecurityConfigComponent
|
||||
} from '@home/components/widget/lib/gateway/connectors-configuration/modbus/modbus-security-config/modbus-security-config.component';
|
||||
import { coerceBoolean } from '@shared/decorators/coercion';
|
||||
import { coerceBoolean, coerceNumber } from '@shared/decorators/coercion';
|
||||
|
||||
@Component({
|
||||
selector: 'tb-report-strategy',
|
||||
@ -73,6 +74,9 @@ export class ReportStrategyComponent implements ControlValueAccessor, OnDestroy
|
||||
@coerceBoolean()
|
||||
@Input() isExpansionMode = false;
|
||||
|
||||
@coerceNumber()
|
||||
@Input() defaultValue = ReportStrategyDefaultValue.Key;
|
||||
|
||||
reportStrategyFormGroup: UntypedFormGroup;
|
||||
showStrategyControl: FormControl<boolean>;
|
||||
|
||||
@ -90,7 +94,7 @@ export class ReportStrategyComponent implements ControlValueAccessor, OnDestroy
|
||||
|
||||
this.reportStrategyFormGroup = this.fb.group({
|
||||
type: [{ value: ReportStrategyType.OnReportPeriod, disabled: true }, []],
|
||||
reportPeriod: [{ value: 5000, disabled: true }, [Validators.required]],
|
||||
reportPeriod: [{ value: this.defaultValue, disabled: true }, [Validators.required]],
|
||||
});
|
||||
|
||||
this.observeStrategyFormChange();
|
||||
@ -109,7 +113,7 @@ export class ReportStrategyComponent implements ControlValueAccessor, OnDestroy
|
||||
if (reportStrategyConfig) {
|
||||
this.reportStrategyFormGroup.enable({emitEvent: false});
|
||||
}
|
||||
const { type = ReportStrategyType.OnReportPeriod, reportPeriod = 5000 } = reportStrategyConfig ?? {};
|
||||
const { type = ReportStrategyType.OnReportPeriod, reportPeriod = this.defaultValue } = reportStrategyConfig ?? {};
|
||||
this.reportStrategyFormGroup.setValue({ type, reportPeriod }, {emitEvent: false});
|
||||
this.onTypeChange(type);
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
<button *ngIf="dataSource?.data?.length"
|
||||
mat-icon-button
|
||||
[disabled]="isLoading$ | async"
|
||||
(click)="addConnector($event)"
|
||||
(click)="onAddConnector($event)"
|
||||
matTooltip="{{ 'action.add' | translate }}"
|
||||
matTooltipPosition="above">
|
||||
<mat-icon>add</mat-icon>
|
||||
@ -33,7 +33,7 @@
|
||||
<section *ngIf="!dataSource?.data?.length" fxLayoutAlign="center center"
|
||||
class="mat-headline-5 tb-absolute-fill tb-add-new">
|
||||
<button mat-button class="connector"
|
||||
(click)="addConnector($event)">
|
||||
(click)="onAddConnector($event)">
|
||||
<mat-icon class="tb-mat-96">add</mat-icon>
|
||||
<span>{{ 'gateway.add-connector' | translate }}</span>
|
||||
</button>
|
||||
@ -244,7 +244,7 @@
|
||||
<button mat-raised-button color="primary"
|
||||
type="button"
|
||||
[disabled]="!connectorForm.dirty || connectorForm.invalid"
|
||||
(click)="saveConnector(false)">
|
||||
(click)="onSaveConnector()">
|
||||
{{ 'action.save' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
@ -315,6 +315,7 @@
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
<tb-report-strategy
|
||||
[defaultValue]="ReportStrategyDefaultValue.Connector"
|
||||
*ngIf="connectorForm.get('type').value === ConnectorType.MODBUS && connectorForm.get('configVersion').value === GatewayVersion.Current"
|
||||
formControlName="reportStrategy"
|
||||
/>
|
||||
|
||||
@ -42,7 +42,7 @@ import { MatTableDataSource } from '@angular/material/table';
|
||||
import { ActionNotificationShow } from '@core/notification/notification.actions';
|
||||
import { DialogService } from '@core/services/dialog.service';
|
||||
import { WidgetContext } from '@home/models/widget-component.models';
|
||||
import { camelCase, deepClone, generateSecret, isEqual, isString } from '@core/utils';
|
||||
import { camelCase, deepClone, isEqual, isString } from '@core/utils';
|
||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
||||
import { IWidgetSubscription, WidgetSubscriptionOptions } from '@core/api/widget-api.models';
|
||||
import { DatasourceType, widgetType } from '@shared/models/widget.models';
|
||||
@ -60,6 +60,8 @@ import {
|
||||
GatewayLogLevel,
|
||||
noLeadTrailSpacesRegex,
|
||||
GatewayVersion,
|
||||
ReportStrategyDefaultValue,
|
||||
ReportStrategyType,
|
||||
} from './gateway-widget.models';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AddConnectorDialogComponent } from '@home/components/widget/lib/gateway/dialog/add-connector-dialog.component';
|
||||
@ -103,6 +105,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
readonly GatewayConnectorTypesTranslatesMap = GatewayConnectorDefaultTypesTranslatesMap;
|
||||
readonly ConnectorConfigurationModes = ConfigurationModes;
|
||||
readonly GatewayVersion = GatewayVersion;
|
||||
readonly ReportStrategyDefaultValue = ReportStrategyDefaultValue;
|
||||
|
||||
pageLink: PageLink;
|
||||
dataSource: MatTableDataSource<GatewayAttributeData>;
|
||||
@ -170,18 +173,21 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
saveConnector(isNew = true): void {
|
||||
const value = this.getConnectorData();
|
||||
onSaveConnector(): void {
|
||||
this.saveConnector(this.getUpdatedConnectorData(this.connectorForm.value), false);
|
||||
}
|
||||
|
||||
private saveConnector(connector: GatewayConnector, isNew = true): void {
|
||||
const scope = (isNew || this.activeConnectors.includes(this.initialConnector.name))
|
||||
? AttributeScope.SHARED_SCOPE
|
||||
: AttributeScope.SERVER_SCOPE;
|
||||
|
||||
forkJoin(this.getEntityAttributeTasks(value, scope)).pipe(take(1)).subscribe(_ => {
|
||||
this.showToast(!this.initialConnector
|
||||
forkJoin(this.getEntityAttributeTasks(connector, scope)).pipe(take(1)).subscribe(_ => {
|
||||
this.showToast(isNew
|
||||
? this.translate.instant('gateway.connector-created')
|
||||
: this.translate.instant('gateway.connector-updated')
|
||||
);
|
||||
this.initialConnector = value;
|
||||
this.initialConnector = connector;
|
||||
this.updateData(true);
|
||||
this.connectorForm.markAsPristine();
|
||||
});
|
||||
@ -237,8 +243,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
}
|
||||
}
|
||||
|
||||
private getConnectorData(): GatewayConnector {
|
||||
const value = { ...this.connectorForm.value };
|
||||
private getUpdatedConnectorData(connector: GatewayConnector): GatewayConnector {
|
||||
const value = {...connector };
|
||||
value.configuration = `${camelCase(value.name)}.json`;
|
||||
delete value.basicConfig;
|
||||
|
||||
@ -249,6 +255,16 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
delete value.class;
|
||||
}
|
||||
|
||||
if (value.type === ConnectorType.MODBUS && value.configVersion === GatewayVersion.Current) {
|
||||
if (!value.reportStrategy) {
|
||||
value.reportStrategy = {
|
||||
type: ReportStrategyType.OnReportPeriod,
|
||||
reportPeriod: ReportStrategyDefaultValue.Connector
|
||||
};
|
||||
delete value.sendDataOnlyOnChange;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.gatewayVersion && !value.configVersion) {
|
||||
value.configVersion = this.gatewayVersion;
|
||||
}
|
||||
@ -472,7 +488,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
return (connector && this.activeConnectors.includes(connectorName)) ? (connector.data[0][1] || 0) : 'Inactive';
|
||||
}
|
||||
|
||||
addConnector(event?: Event): void {
|
||||
onAddConnector(event?: Event): void {
|
||||
event?.stopPropagation();
|
||||
|
||||
this.confirmConnectorChange()
|
||||
@ -482,25 +498,42 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
switchMap(() => this.openAddConnectorDialog()),
|
||||
filter(Boolean),
|
||||
)
|
||||
.subscribe(value => {
|
||||
.subscribe(connector => this.addConnector(connector));
|
||||
}
|
||||
|
||||
private addConnector(connector: GatewayConnector): void {
|
||||
if (this.connectorForm.disabled) {
|
||||
this.connectorForm.enable();
|
||||
}
|
||||
if (!value.configurationJson) {
|
||||
value.configurationJson = {} as ConnectorBaseConfig;
|
||||
if (!connector.configurationJson) {
|
||||
connector.configurationJson = {} as ConnectorBaseConfig;
|
||||
}
|
||||
value.basicConfig = value.configurationJson;
|
||||
this.initialConnector = value;
|
||||
this.connectorForm.patchValue(value, {emitEvent: false});
|
||||
this.generate('basicConfig.broker.clientId');
|
||||
if (this.connectorForm.get('type').value === value.type || !this.allowBasicConfig.has(value.type)) {
|
||||
this.saveConnector();
|
||||
connector.basicConfig = connector.configurationJson;
|
||||
this.initialConnector = connector;
|
||||
|
||||
const previousType = this.connectorForm.get('type').value;
|
||||
|
||||
this.setInitialConnectorValues(connector);
|
||||
|
||||
this.saveConnector(this.getUpdatedConnectorData(connector));
|
||||
|
||||
if (!previousType || previousType === connector.type || !this.allowBasicConfig.has(connector.type)) {
|
||||
this.patchBasicConfigConnector(connector);
|
||||
} else {
|
||||
this.basicConfigInitSubject.pipe(take(1)).subscribe(() => {
|
||||
this.saveConnector();
|
||||
this.patchBasicConfigConnector(connector);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private setInitialConnectorValues(connector: GatewayConnector): void {
|
||||
this.toggleReportStrategy(connector.type);
|
||||
this.connectorForm.get('mode').setValue(this.allowBasicConfig.has(connector.type)
|
||||
? connector.mode ?? ConfigurationModes.BASIC
|
||||
: null, {emitEvent: false}
|
||||
);
|
||||
this.connectorForm.get('configVersion').setValue(connector.configVersion, {emitEvent: false});
|
||||
this.connectorForm.get('type').setValue(connector.type, {emitEvent: false});
|
||||
}
|
||||
|
||||
private openAddConnectorDialog(): Observable<GatewayConnector> {
|
||||
@ -514,10 +547,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
}).afterClosed();
|
||||
}
|
||||
|
||||
generate(formControlName: string): void {
|
||||
this.connectorForm.get(formControlName)?.patchValue('tb_gw_' + generateSecret(5));
|
||||
}
|
||||
|
||||
uniqNameRequired(): ValidatorFn {
|
||||
return (control: UntypedFormControl) => {
|
||||
const newName = control.value?.trim().toLowerCase();
|
||||
@ -607,7 +636,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
|
||||
const active = attributes.find(data => data.key === 'active').value;
|
||||
const lastDisconnectedTime = attributes.find(data => data.key === 'lastDisconnectTime')?.value;
|
||||
const lastConnectedTime = attributes.find(data => data.key === 'lastConnectTime').value;
|
||||
const lastConnectedTime = attributes.find(data => data.key === 'lastConnectTime')?.value;
|
||||
|
||||
this.isGatewayActive = this.getGatewayStatus(active, lastConnectedTime, lastDisconnectedTime);
|
||||
});
|
||||
@ -804,7 +833,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
}
|
||||
|
||||
private updateConnector(connector: GatewayConnector): void {
|
||||
this.toggleReportStrategy(connector.type);
|
||||
switch (connector.type) {
|
||||
case ConnectorType.MQTT:
|
||||
case ConnectorType.OPCUA:
|
||||
@ -819,8 +847,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
||||
}
|
||||
|
||||
private updateBasicConfigConnector(connector: GatewayConnector): void {
|
||||
this.connectorForm.get('mode').setValue(connector.mode || ConfigurationModes.BASIC, {emitEvent: false});
|
||||
this.connectorForm.get('configVersion').setValue(connector.configVersion, {emitEvent: false});
|
||||
this.setInitialConnectorValues(connector);
|
||||
if ((!connector.mode || connector.mode === ConfigurationModes.BASIC) && this.connectorForm.get('type').value !== connector.type) {
|
||||
this.basicConfigInitSubject.asObservable().pipe(take(1)).subscribe(() => {
|
||||
this.patchBasicConfigConnector(connector);
|
||||
|
||||
@ -123,6 +123,9 @@ export interface GatewayConnectorBase {
|
||||
class?: string;
|
||||
mode?: ConfigurationModes;
|
||||
configVersion?: string;
|
||||
reportStrategy?: ReportStrategyConfig;
|
||||
sendDataOnlyOnChange?: boolean;
|
||||
ts?: number;
|
||||
}
|
||||
|
||||
export interface GatewayConnector<BaseConfig = ConnectorBaseConfig> extends GatewayConnectorBase {
|
||||
@ -645,6 +648,12 @@ export enum ReportStrategyType {
|
||||
OnChangeOrReportPeriod = 'ON_CHANGE_OR_REPORT_PERIOD'
|
||||
}
|
||||
|
||||
export enum ReportStrategyDefaultValue {
|
||||
Connector = 60000,
|
||||
Device = 30000,
|
||||
Key = 15000
|
||||
}
|
||||
|
||||
export const ReportStrategyTypeTranslationsMap = new Map<ReportStrategyType, string>(
|
||||
[
|
||||
[ReportStrategyType.OnChange, 'gateway.report-strategy.on-change'],
|
||||
|
||||
@ -2955,7 +2955,6 @@
|
||||
"configuration-delete-dialog-confirm": "Turn Off",
|
||||
"connector-duplicate-name": "Connector with such name already exists.",
|
||||
"connector-side": "Connector side",
|
||||
"client-communication-type": "Client communication type",
|
||||
"payload-type": "Payload type",
|
||||
"platform-side": "Platform side",
|
||||
"JSON": "JSON",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user