Gateway fixes and added support for newer Gateway versions
This commit is contained in:
parent
97243cad43
commit
38b0e4fb02
@ -15,15 +15,17 @@
|
|||||||
///
|
///
|
||||||
|
|
||||||
import { GatewayConnector, GatewayVersion } from '@home/components/widget/lib/gateway/gateway-widget.models';
|
import { GatewayConnector, GatewayVersion } from '@home/components/widget/lib/gateway/gateway-widget.models';
|
||||||
import { isNumber, isString } from '@core/utils';
|
import {
|
||||||
|
GatewayConnectorVersionMappingUtil
|
||||||
|
} from '@home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util';
|
||||||
|
|
||||||
export abstract class GatewayConnectorVersionProcessor<BasicConfig> {
|
export abstract class GatewayConnectorVersionProcessor<BasicConfig> {
|
||||||
gatewayVersion: number;
|
gatewayVersion: number;
|
||||||
configVersion: number;
|
configVersion: number;
|
||||||
|
|
||||||
protected constructor(protected gatewayVersionIn: string | number, protected connector: GatewayConnector<BasicConfig>) {
|
protected constructor(protected gatewayVersionIn: string | number, protected connector: GatewayConnector<BasicConfig>) {
|
||||||
this.gatewayVersion = this.parseVersion(this.gatewayVersionIn);
|
this.gatewayVersion = GatewayConnectorVersionMappingUtil.parseVersion(this.gatewayVersionIn);
|
||||||
this.configVersion = this.parseVersion(this.connector.configVersion);
|
this.configVersion = GatewayConnectorVersionMappingUtil.parseVersion(this.connector.configVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
getProcessedByVersion(): GatewayConnector<BasicConfig> {
|
getProcessedByVersion(): GatewayConnector<BasicConfig> {
|
||||||
@ -53,19 +55,13 @@ export abstract class GatewayConnectorVersionProcessor<BasicConfig> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isVersionUpgradeNeeded(): boolean {
|
private isVersionUpgradeNeeded(): boolean {
|
||||||
return this.gatewayVersionIn === GatewayVersion.Current && (!this.configVersion || this.configVersion < this.gatewayVersion);
|
return this.gatewayVersion >= GatewayConnectorVersionMappingUtil.parseVersion(GatewayVersion.Current)
|
||||||
|
&& (!this.configVersion || this.configVersion < this.gatewayVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private isVersionDowngradeNeeded(): boolean {
|
private isVersionDowngradeNeeded(): boolean {
|
||||||
return this.configVersion && this.connector.configVersion === GatewayVersion.Current && (this.configVersion > this.gatewayVersion);
|
return this.configVersion && this.configVersion >= GatewayConnectorVersionMappingUtil.parseVersion(GatewayVersion.Current)
|
||||||
}
|
&& (this.configVersion > this.gatewayVersion);
|
||||||
|
|
||||||
private parseVersion(version: string | number): number {
|
|
||||||
if (isNumber(version)) {
|
|
||||||
return version as number;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isString(version) ? parseFloat((version as string).replace(/\./g, '').slice(0, 3)) / 100 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract getDowngradedVersion(): GatewayConnector<BasicConfig>;
|
protected abstract getDowngradedVersion(): GatewayConnector<BasicConfig>;
|
||||||
|
|||||||
@ -126,6 +126,7 @@ export class SecurityConfigComponent implements ControlValueAccessor, OnInit, On
|
|||||||
if (!securityInfo.type) {
|
if (!securityInfo.type) {
|
||||||
securityInfo.type = SecurityType.ANONYMOUS;
|
securityInfo.type = SecurityType.ANONYMOUS;
|
||||||
}
|
}
|
||||||
|
this.updateValidators(securityInfo.type);
|
||||||
this.securityFormGroup.reset(securityInfo, {emitEvent: false});
|
this.securityFormGroup.reset(securityInfo, {emitEvent: false});
|
||||||
}
|
}
|
||||||
this.cdr.markForCheck();
|
this.cdr.markForCheck();
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import { Observable, Subject } from 'rxjs';
|
|||||||
import { ResourcesService } from '@core/services/resources.service';
|
import { ResourcesService } from '@core/services/resources.service';
|
||||||
import { takeUntil, tap } from 'rxjs/operators';
|
import { takeUntil, tap } from 'rxjs/operators';
|
||||||
import { helpBaseUrl } from '@shared/models/constants';
|
import { helpBaseUrl } from '@shared/models/constants';
|
||||||
|
import { LatestVersionConfigPipe } from '@home/components/widget/lib/gateway/pipes/latest-version-config.pipe';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-add-connector-dialog',
|
selector: 'tb-add-connector-dialog',
|
||||||
@ -63,6 +64,7 @@ export class AddConnectorDialogComponent
|
|||||||
@Inject(MAT_DIALOG_DATA) public data: AddConnectorConfigData,
|
@Inject(MAT_DIALOG_DATA) public data: AddConnectorConfigData,
|
||||||
public dialogRef: MatDialogRef<AddConnectorDialogComponent, CreatedConnectorConfigData>,
|
public dialogRef: MatDialogRef<AddConnectorDialogComponent, CreatedConnectorConfigData>,
|
||||||
private fb: FormBuilder,
|
private fb: FormBuilder,
|
||||||
|
private isLatestVersionConfig: LatestVersionConfigPipe,
|
||||||
private resourcesService: ResourcesService) {
|
private resourcesService: ResourcesService) {
|
||||||
super(store, router, dialogRef);
|
super(store, router, dialogRef);
|
||||||
this.connectorForm = this.fb.group({
|
this.connectorForm = this.fb.group({
|
||||||
@ -103,9 +105,9 @@ export class AddConnectorDialogComponent
|
|||||||
if (gatewayVersion) {
|
if (gatewayVersion) {
|
||||||
value.configVersion = gatewayVersion;
|
value.configVersion = gatewayVersion;
|
||||||
}
|
}
|
||||||
value.configurationJson = (gatewayVersion === GatewayVersion.Current
|
value.configurationJson = (this.isLatestVersionConfig.transform(gatewayVersion)
|
||||||
? defaultConfig[this.data.gatewayVersion]
|
? defaultConfig[GatewayVersion.Current]
|
||||||
: defaultConfig.legacy)
|
: defaultConfig[GatewayVersion.Legacy])
|
||||||
?? defaultConfig;
|
?? defaultConfig;
|
||||||
if (this.connectorForm.valid) {
|
if (this.connectorForm.valid) {
|
||||||
this.dialogRef.close(value);
|
this.dialogRef.close(value);
|
||||||
|
|||||||
@ -178,7 +178,7 @@
|
|||||||
<ng-container [ngSwitch]="initialConnector.type">
|
<ng-container [ngSwitch]="initialConnector.type">
|
||||||
<ng-container *ngSwitchCase="ConnectorType.MQTT">
|
<ng-container *ngSwitchCase="ConnectorType.MQTT">
|
||||||
<tb-mqtt-basic-config
|
<tb-mqtt-basic-config
|
||||||
*ngIf="connectorForm.get('configVersion').value === GatewayVersion.Current else legacy"
|
*ngIf="connectorForm.get('configVersion').value | isLatestVersionConfig else legacy"
|
||||||
formControlName="basicConfig"
|
formControlName="basicConfig"
|
||||||
[generalTabContent]="generalTabContent"
|
[generalTabContent]="generalTabContent"
|
||||||
(initialized)="basicConfigInitSubject.next()"
|
(initialized)="basicConfigInitSubject.next()"
|
||||||
@ -193,7 +193,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngSwitchCase="ConnectorType.OPCUA">
|
<ng-container *ngSwitchCase="ConnectorType.OPCUA">
|
||||||
<tb-opc-ua-basic-config
|
<tb-opc-ua-basic-config
|
||||||
*ngIf="connectorForm.get('configVersion').value === GatewayVersion.Current else legacy"
|
*ngIf="connectorForm.get('configVersion').value | isLatestVersionConfig else legacy"
|
||||||
formControlName="basicConfig"
|
formControlName="basicConfig"
|
||||||
[generalTabContent]="generalTabContent"
|
[generalTabContent]="generalTabContent"
|
||||||
(initialized)="basicConfigInitSubject.next()"
|
(initialized)="basicConfigInitSubject.next()"
|
||||||
@ -208,7 +208,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngSwitchCase="ConnectorType.MODBUS">
|
<ng-container *ngSwitchCase="ConnectorType.MODBUS">
|
||||||
<tb-modbus-basic-config
|
<tb-modbus-basic-config
|
||||||
*ngIf="connectorForm.get('configVersion').value === GatewayVersion.Current else legacy"
|
*ngIf="connectorForm.get('configVersion').value | isLatestVersionConfig else legacy"
|
||||||
formControlName="basicConfig"
|
formControlName="basicConfig"
|
||||||
[generalTabContent]="generalTabContent"
|
[generalTabContent]="generalTabContent"
|
||||||
(initialized)="basicConfigInitSubject.next()"
|
(initialized)="basicConfigInitSubject.next()"
|
||||||
@ -316,7 +316,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<tb-report-strategy
|
<tb-report-strategy
|
||||||
[defaultValue]="ReportStrategyDefaultValue.Connector"
|
[defaultValue]="ReportStrategyDefaultValue.Connector"
|
||||||
*ngIf="connectorForm.get('type').value === ConnectorType.MODBUS && connectorForm.get('configVersion').value === GatewayVersion.Current"
|
*ngIf="connectorForm.get('type').value === ConnectorType.MODBUS && (connectorForm.get('configVersion').value | isLatestVersionConfig)"
|
||||||
formControlName="reportStrategy"
|
formControlName="reportStrategy"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -59,7 +59,6 @@ import {
|
|||||||
GatewayConnectorDefaultTypesTranslatesMap,
|
GatewayConnectorDefaultTypesTranslatesMap,
|
||||||
GatewayLogLevel,
|
GatewayLogLevel,
|
||||||
noLeadTrailSpacesRegex,
|
noLeadTrailSpacesRegex,
|
||||||
GatewayVersion,
|
|
||||||
ReportStrategyDefaultValue,
|
ReportStrategyDefaultValue,
|
||||||
ReportStrategyType,
|
ReportStrategyType,
|
||||||
} from './gateway-widget.models';
|
} from './gateway-widget.models';
|
||||||
@ -71,6 +70,7 @@ import { PageData } from '@shared/models/page/page-data';
|
|||||||
import {
|
import {
|
||||||
GatewayConnectorVersionMappingUtil
|
GatewayConnectorVersionMappingUtil
|
||||||
} from '@home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util';
|
} from '@home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util';
|
||||||
|
import { LatestVersionConfigPipe } from '@home/components/widget/lib/gateway/pipes/latest-version-config.pipe';
|
||||||
|
|
||||||
export class ForceErrorStateMatcher implements ErrorStateMatcher {
|
export class ForceErrorStateMatcher implements ErrorStateMatcher {
|
||||||
isErrorState(control: FormControl | null): boolean {
|
isErrorState(control: FormControl | null): boolean {
|
||||||
@ -104,7 +104,6 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
readonly displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions'];
|
readonly displayedColumns = ['enabled', 'key', 'type', 'syncStatus', 'errors', 'actions'];
|
||||||
readonly GatewayConnectorTypesTranslatesMap = GatewayConnectorDefaultTypesTranslatesMap;
|
readonly GatewayConnectorTypesTranslatesMap = GatewayConnectorDefaultTypesTranslatesMap;
|
||||||
readonly ConnectorConfigurationModes = ConfigurationModes;
|
readonly ConnectorConfigurationModes = ConfigurationModes;
|
||||||
readonly GatewayVersion = GatewayVersion;
|
|
||||||
readonly ReportStrategyDefaultValue = ReportStrategyDefaultValue;
|
readonly ReportStrategyDefaultValue = ReportStrategyDefaultValue;
|
||||||
|
|
||||||
pageLink: PageLink;
|
pageLink: PageLink;
|
||||||
@ -149,6 +148,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
private telemetryWsService: TelemetryWebsocketService,
|
private telemetryWsService: TelemetryWebsocketService,
|
||||||
private zone: NgZone,
|
private zone: NgZone,
|
||||||
private utils: UtilsService,
|
private utils: UtilsService,
|
||||||
|
private isLatestVersionConfig: LatestVersionConfigPipe,
|
||||||
private cd: ChangeDetectorRef) {
|
private cd: ChangeDetectorRef) {
|
||||||
super(store);
|
super(store);
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
delete value.class;
|
delete value.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.type === ConnectorType.MODBUS && value.configVersion === GatewayVersion.Current) {
|
if (value.type === ConnectorType.MODBUS && this.isLatestVersionConfig.transform(value.configVersion)) {
|
||||||
if (!value.reportStrategy) {
|
if (!value.reportStrategy) {
|
||||||
value.reportStrategy = {
|
value.reportStrategy = {
|
||||||
type: ReportStrategyType.OnReportPeriod,
|
type: ReportStrategyType.OnReportPeriod,
|
||||||
@ -508,6 +508,9 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
if (!connector.configurationJson) {
|
if (!connector.configurationJson) {
|
||||||
connector.configurationJson = {} as ConnectorBaseConfig;
|
connector.configurationJson = {} as ConnectorBaseConfig;
|
||||||
}
|
}
|
||||||
|
if (this.gatewayVersion && !connector.configVersion) {
|
||||||
|
connector.configVersion = this.gatewayVersion;
|
||||||
|
}
|
||||||
connector.basicConfig = connector.configurationJson;
|
connector.basicConfig = connector.configurationJson;
|
||||||
this.initialConnector = connector;
|
this.initialConnector = connector;
|
||||||
|
|
||||||
@ -517,7 +520,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
|
|
||||||
this.saveConnector(this.getUpdatedConnectorData(connector));
|
this.saveConnector(this.getUpdatedConnectorData(connector));
|
||||||
|
|
||||||
if (!previousType || previousType === connector.type || !this.allowBasicConfig.has(connector.type)) {
|
if (previousType === connector.type || !this.allowBasicConfig.has(connector.type)) {
|
||||||
this.patchBasicConfigConnector(connector);
|
this.patchBasicConfigConnector(connector);
|
||||||
} else {
|
} else {
|
||||||
this.basicConfigInitSubject.pipe(take(1)).subscribe(() => {
|
this.basicConfigInitSubject.pipe(take(1)).subscribe(() => {
|
||||||
@ -527,24 +530,26 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
private setInitialConnectorValues(connector: GatewayConnector): void {
|
private setInitialConnectorValues(connector: GatewayConnector): void {
|
||||||
|
const {basicConfig, mode, ...initialConnector} = connector;
|
||||||
this.toggleReportStrategy(connector.type);
|
this.toggleReportStrategy(connector.type);
|
||||||
this.connectorForm.get('mode').setValue(this.allowBasicConfig.has(connector.type)
|
this.connectorForm.get('mode').setValue(this.allowBasicConfig.has(connector.type)
|
||||||
? connector.mode ?? ConfigurationModes.BASIC
|
? connector.mode ?? ConfigurationModes.BASIC
|
||||||
: null, {emitEvent: false}
|
: null, {emitEvent: false}
|
||||||
);
|
);
|
||||||
this.connectorForm.get('configVersion').setValue(connector.configVersion, {emitEvent: false});
|
this.connectorForm.patchValue(initialConnector, {emitEvent: false});
|
||||||
this.connectorForm.get('type').setValue(connector.type, {emitEvent: false});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private openAddConnectorDialog(): Observable<GatewayConnector> {
|
private openAddConnectorDialog(): Observable<GatewayConnector> {
|
||||||
return this.dialog.open<AddConnectorDialogComponent, AddConnectorConfigData>(AddConnectorDialogComponent, {
|
return this.ctx.ngZone.run(() =>
|
||||||
|
this.dialog.open<AddConnectorDialogComponent, AddConnectorConfigData>(AddConnectorDialogComponent, {
|
||||||
disableClose: true,
|
disableClose: true,
|
||||||
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
|
||||||
data: {
|
data: {
|
||||||
dataSourceData: this.dataSource.data,
|
dataSourceData: this.dataSource.data,
|
||||||
gatewayVersion: this.gatewayVersion,
|
gatewayVersion: this.gatewayVersion,
|
||||||
}
|
}
|
||||||
}).afterClosed();
|
}).afterClosed()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
uniqNameRequired(): ValidatorFn {
|
uniqNameRequired(): ValidatorFn {
|
||||||
@ -650,13 +655,8 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
private observeModeChange(): void {
|
private observeModeChange(): void {
|
||||||
this.connectorForm.get('mode').valueChanges
|
this.connectorForm.get('mode').valueChanges
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe((mode) => {
|
.subscribe(() => {
|
||||||
this.connectorForm.get('mode').markAsPristine();
|
this.connectorForm.get('mode').markAsPristine();
|
||||||
if (mode === ConfigurationModes.BASIC) {
|
|
||||||
this.basicConfigInitSubject.pipe(take(1)).subscribe(() => {
|
|
||||||
this.patchBasicConfigConnector({...this.initialConnector, mode: ConfigurationModes.BASIC});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -827,12 +827,17 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
...connector,
|
...connector,
|
||||||
}, this.gatewayVersion);
|
}, this.gatewayVersion);
|
||||||
|
|
||||||
|
if (this.gatewayVersion && !connectorState.configVersion) {
|
||||||
|
connectorState.configVersion = this.gatewayVersion;
|
||||||
|
}
|
||||||
|
|
||||||
connectorState.basicConfig = connectorState.configurationJson;
|
connectorState.basicConfig = connectorState.configurationJson;
|
||||||
this.initialConnector = connectorState;
|
this.initialConnector = connectorState;
|
||||||
this.updateConnector(connectorState);
|
this.updateConnector(connectorState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateConnector(connector: GatewayConnector): void {
|
private updateConnector(connector: GatewayConnector): void {
|
||||||
|
this.jsonConfigSub?.unsubscribe();
|
||||||
switch (connector.type) {
|
switch (connector.type) {
|
||||||
case ConnectorType.MQTT:
|
case ConnectorType.MQTT:
|
||||||
case ConnectorType.OPCUA:
|
case ConnectorType.OPCUA:
|
||||||
@ -842,18 +847,21 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
default:
|
default:
|
||||||
this.connectorForm.patchValue({...connector, mode: null});
|
this.connectorForm.patchValue({...connector, mode: null});
|
||||||
this.connectorForm.markAsPristine();
|
this.connectorForm.markAsPristine();
|
||||||
}
|
|
||||||
this.createJsonConfigWatcher();
|
this.createJsonConfigWatcher();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private updateBasicConfigConnector(connector: GatewayConnector): void {
|
private updateBasicConfigConnector(connector: GatewayConnector): void {
|
||||||
|
this.basicConfigSub?.unsubscribe();
|
||||||
|
const previousType = this.connectorForm.get('type').value;
|
||||||
this.setInitialConnectorValues(connector);
|
this.setInitialConnectorValues(connector);
|
||||||
if ((!connector.mode || connector.mode === ConfigurationModes.BASIC) && this.connectorForm.get('type').value !== connector.type) {
|
|
||||||
|
if (previousType === connector.type || !this.allowBasicConfig.has(connector.type)) {
|
||||||
|
this.patchBasicConfigConnector(connector);
|
||||||
|
} else {
|
||||||
this.basicConfigInitSubject.asObservable().pipe(take(1)).subscribe(() => {
|
this.basicConfigInitSubject.asObservable().pipe(take(1)).subscribe(() => {
|
||||||
this.patchBasicConfigConnector(connector);
|
this.patchBasicConfigConnector(connector);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
this.patchBasicConfigConnector(connector);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -861,6 +869,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
this.connectorForm.patchValue(connector, {emitEvent: false});
|
this.connectorForm.patchValue(connector, {emitEvent: false});
|
||||||
this.connectorForm.markAsPristine();
|
this.connectorForm.markAsPristine();
|
||||||
this.createBasicConfigWatcher();
|
this.createBasicConfigWatcher();
|
||||||
|
this.createJsonConfigWatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
private toggleReportStrategy(type: ConnectorType): void {
|
private toggleReportStrategy(type: ConnectorType): void {
|
||||||
|
|||||||
@ -33,6 +33,8 @@ export class GatewayHelpLinkPipe implements PipeTransform {
|
|||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (field === 'attributes' || field === 'timeseries') {
|
||||||
|
return 'widget/lib/gateway/attributes_timeseries_expressions_fn';
|
||||||
}
|
}
|
||||||
return 'widget/lib/gateway/expressions_fn';
|
return 'widget/lib/gateway/expressions_fn';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,32 @@
|
|||||||
|
///
|
||||||
|
/// 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 { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
import { GatewayVersion } from '@home/components/widget/lib/gateway/gateway-widget.models';
|
||||||
|
import {
|
||||||
|
GatewayConnectorVersionMappingUtil
|
||||||
|
} from '@home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'isLatestVersionConfig',
|
||||||
|
standalone: true,
|
||||||
|
})
|
||||||
|
export class LatestVersionConfigPipe implements PipeTransform {
|
||||||
|
transform(configVersion: number | string): boolean {
|
||||||
|
return GatewayConnectorVersionMappingUtil.parseVersion(configVersion)
|
||||||
|
>= GatewayConnectorVersionMappingUtil.parseVersion(GatewayVersion.Current);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,6 +24,7 @@ import {
|
|||||||
import { MqttVersionProcessor } from '@home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract';
|
import { MqttVersionProcessor } from '@home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract';
|
||||||
import { OpcVersionProcessor } from '@home/components/widget/lib/gateway/abstract/opc-version-processor.abstract';
|
import { OpcVersionProcessor } from '@home/components/widget/lib/gateway/abstract/opc-version-processor.abstract';
|
||||||
import { ModbusVersionProcessor } from '@home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract';
|
import { ModbusVersionProcessor } from '@home/components/widget/lib/gateway/abstract/modbus-version-processor.abstract';
|
||||||
|
import { isNumber, isString } from '@core/utils';
|
||||||
|
|
||||||
export abstract class GatewayConnectorVersionMappingUtil {
|
export abstract class GatewayConnectorVersionMappingUtil {
|
||||||
|
|
||||||
@ -39,4 +40,12 @@ export abstract class GatewayConnectorVersionMappingUtil {
|
|||||||
return connector;
|
return connector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static parseVersion(version: string | number): number {
|
||||||
|
if (isNumber(version)) {
|
||||||
|
return version as number;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isString(version) ? parseFloat((version as string).replace(/\./g, '').slice(0, 3)) / 100 : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export class OpcVersionMappingUtil {
|
|||||||
static mapMappingToUpgradedVersion(mapping: LegacyDeviceConnectorMapping[]): DeviceConnectorMapping[] {
|
static mapMappingToUpgradedVersion(mapping: LegacyDeviceConnectorMapping[]): DeviceConnectorMapping[] {
|
||||||
return mapping.map((legacyMapping: LegacyDeviceConnectorMapping) => ({
|
return mapping.map((legacyMapping: LegacyDeviceConnectorMapping) => ({
|
||||||
...legacyMapping,
|
...legacyMapping,
|
||||||
deviceNodeSource: this.getTypeSourceByValue(legacyMapping.deviceNodePattern),
|
deviceNodeSource: this.getDeviceNodeSourceByValue(legacyMapping.deviceNodePattern),
|
||||||
deviceInfo: {
|
deviceInfo: {
|
||||||
deviceNameExpression: legacyMapping.deviceNamePattern,
|
deviceNameExpression: legacyMapping.deviceNamePattern,
|
||||||
deviceNameExpressionSource: this.getTypeSourceByValue(legacyMapping.deviceNamePattern),
|
deviceNameExpressionSource: this.getTypeSourceByValue(legacyMapping.deviceNamePattern),
|
||||||
@ -122,6 +122,14 @@ export class OpcVersionMappingUtil {
|
|||||||
return OPCUaSourceType.CONST;
|
return OPCUaSourceType.CONST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static getDeviceNodeSourceByValue(value: string): OPCUaSourceType {
|
||||||
|
if (value.includes('${')) {
|
||||||
|
return OPCUaSourceType.IDENTIFIER;
|
||||||
|
} else {
|
||||||
|
return OPCUaSourceType.PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static getArgumentType(arg: unknown): string {
|
private static getArgumentType(arg: unknown): string {
|
||||||
switch (typeof arg) {
|
switch (typeof arg) {
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
|
|||||||
@ -170,6 +170,7 @@ import { RpcTemplateArrayViewPipe } from '@home/components/widget/lib/gateway/pi
|
|||||||
import {
|
import {
|
||||||
ReportStrategyComponent
|
ReportStrategyComponent
|
||||||
} from '@home/components/widget/lib/gateway/connectors-configuration/report-strategy/report-strategy.component';
|
} from '@home/components/widget/lib/gateway/connectors-configuration/report-strategy/report-strategy.component';
|
||||||
|
import { LatestVersionConfigPipe } from '@home/components/widget/lib/gateway/pipes/latest-version-config.pipe';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -268,6 +269,7 @@ import {
|
|||||||
ModbusRpcParametersComponent,
|
ModbusRpcParametersComponent,
|
||||||
RpcTemplateArrayViewPipe,
|
RpcTemplateArrayViewPipe,
|
||||||
ReportStrategyComponent,
|
ReportStrategyComponent,
|
||||||
|
LatestVersionConfigPipe,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
EntitiesTableWidgetComponent,
|
EntitiesTableWidgetComponent,
|
||||||
@ -337,7 +339,8 @@ import {
|
|||||||
ScadaSymbolWidgetComponent
|
ScadaSymbolWidgetComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{provide: WIDGET_COMPONENTS_MODULE_TOKEN, useValue: WidgetComponentsModule}
|
{provide: WIDGET_COMPONENTS_MODULE_TOKEN, useValue: WidgetComponentsModule},
|
||||||
|
{provide: LatestVersionConfigPipe}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class WidgetComponentsModule {
|
export class WidgetComponentsModule {
|
||||||
|
|||||||
@ -0,0 +1,65 @@
|
|||||||
|
### Expressions
|
||||||
|
#### JSON Path:
|
||||||
|
|
||||||
|
The expression field is used to extract data from the MQTT message. There are various available options for different parts of the messages:
|
||||||
|
|
||||||
|
- The JSONPath format can be used to extract data from the message body.
|
||||||
|
|
||||||
|
- The regular expression format can be used to extract data from the topic where the message will arrive.
|
||||||
|
|
||||||
|
- Slices can only be used in the expression fields of bytes converters.
|
||||||
|
|
||||||
|
JSONPath expressions specify the items within a JSON structure (which could be an object, array, or nested combination of both) that you want to access. These expressions can select elements from JSON data on specific criteria. Here's a basic overview of how JSONPath expressions are structured:
|
||||||
|
|
||||||
|
- `$`: The root element of the JSON document;
|
||||||
|
|
||||||
|
- `.`: Child operator used to select child elements. For example, $.store.book ;
|
||||||
|
|
||||||
|
- `[]`: Child operator used to select child elements. $['store']['book'] accesses the book array within a store object;
|
||||||
|
|
||||||
|
##### Examples:
|
||||||
|
|
||||||
|
For example, if we want to extract the device name from the following message, we can use the expression below:
|
||||||
|
|
||||||
|
MQTT message:
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"sensorModelInfo": {
|
||||||
|
"sensorName": "AM-123",
|
||||||
|
"sensorType": "myDeviceType"
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"temp": 12.2,
|
||||||
|
"hum": 56,
|
||||||
|
"status": "ok"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{:copy-code}
|
||||||
|
```
|
||||||
|
|
||||||
|
Expression:
|
||||||
|
|
||||||
|
`${sensorModelInfo.sensorName}`
|
||||||
|
|
||||||
|
Converted data:
|
||||||
|
|
||||||
|
`AM-123`
|
||||||
|
|
||||||
|
If we want to extract all data from the message above, we can use the following expression:
|
||||||
|
|
||||||
|
`${data}`
|
||||||
|
|
||||||
|
Converted data:
|
||||||
|
|
||||||
|
`{"temp": 12.2, "hum": 56, "status": "ok"}`
|
||||||
|
|
||||||
|
Or if we want to extract specific data (for example “temperature”), you can use the following expression:
|
||||||
|
|
||||||
|
`${data.temp}`
|
||||||
|
|
||||||
|
And as a converted data we will get:
|
||||||
|
|
||||||
|
`12.2`
|
||||||
|
|
||||||
|
<br/>
|
||||||
@ -20,13 +20,21 @@
|
|||||||
"connectAttemptTimeMs": 5000,
|
"connectAttemptTimeMs": 5000,
|
||||||
"connectAttemptCount": 5,
|
"connectAttemptCount": 5,
|
||||||
"waitAfterFailedAttemptsMs": 300000,
|
"waitAfterFailedAttemptsMs": 300000,
|
||||||
|
"reportStrategy": {
|
||||||
|
"type": "ON_REPORT_PERIOD",
|
||||||
|
"reportPeriod": 30000
|
||||||
|
},
|
||||||
"attributes": [
|
"attributes": [
|
||||||
{
|
{
|
||||||
"tag": "string_read",
|
"tag": "string_read",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"functionCode": 4,
|
"functionCode": 4,
|
||||||
"objectsCount": 4,
|
"objectsCount": 4,
|
||||||
"address": 1
|
"address": 1,
|
||||||
|
"reportStrategy": {
|
||||||
|
"type": "ON_REPORT_PERIOD",
|
||||||
|
"reportPeriod": 15000
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "bits_read",
|
"tag": "bits_read",
|
||||||
@ -86,7 +94,11 @@
|
|||||||
"type": "8uint",
|
"type": "8uint",
|
||||||
"functionCode": 4,
|
"functionCode": 4,
|
||||||
"objectsCount": 1,
|
"objectsCount": 1,
|
||||||
"address": 17
|
"address": 17,
|
||||||
|
"reportStrategy": {
|
||||||
|
"type": "ON_REPORT_PERIOD",
|
||||||
|
"reportPeriod": 15000
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "16uint_read",
|
"tag": "16uint_read",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user