changed approach to abstract class for mapping

This commit is contained in:
mpetrov 2024-09-09 15:30:57 +03:00
parent d66130fc2c
commit c4441eba72
11 changed files with 168 additions and 149 deletions

View File

@ -0,0 +1,36 @@
import { GatewayConnector } from '@home/components/widget/lib/gateway/gateway-widget.models';
export abstract class GatewayConnectorVersionProcessor<BasicConfig> {
gatewayVersion: number;
configVersion: number;
protected constructor(protected gatewayVersionStr: string, protected connector: GatewayConnector) {
this.gatewayVersion = this.parseVersion(this.gatewayVersionStr);
this.configVersion = this.parseVersion(connector.configVersion);
}
getProcessedByVersion(): BasicConfig {
if (this.isVersionUpdateNeeded()) {
return this.configVersion > this.gatewayVersion
? this.getDowngradedVersion()
: this.getUpgradedVersion();
}
return this.connector.configurationJson as unknown as BasicConfig;
}
private isVersionUpdateNeeded(): boolean {
if (!this.gatewayVersion || !this.configVersion) {
return false;
}
return this.configVersion !== this.gatewayVersion;
}
private parseVersion(version: string): number {
return Number(version?.replace(/\./g, ''));
}
abstract getDowngradedVersion(): BasicConfig;
abstract getUpgradedVersion(): BasicConfig;
}

View File

@ -0,0 +1,76 @@
import {
GatewayConnectorVersionProcessor
} from '@home/components/widget/lib/gateway/abstract/gateway-connector-version-processor.abstract';
import {
GatewayConnector,
MQTTBasicConfig, MQTTBasicConfig_v3_5_2,
MQTTLegacyBasicConfig,
RequestMappingData,
RequestType,
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { isEqual } from '@core/utils';
import { MqttVersionMappingUtil } from '@home/components/widget/lib/gateway/utils/mqtt-version-mapping.util';
export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTBasicConfig> {
private readonly mqttRequestTypeKeys = Object.values(RequestType);
constructor(
protected gatewayVersionStr: string,
protected connector: GatewayConnector
) {
super(gatewayVersionStr, connector);
}
getUpgradedVersion(): MQTTBasicConfig {
const {
connectRequests,
disconnectRequests,
attributeRequests,
attributeUpdates,
serverSideRpc
} = this.connector.configurationJson as MQTTLegacyBasicConfig;
let configurationJson = {
...this.connector.configurationJson,
requestsMapping: MqttVersionMappingUtil.mapRequestsToUpgradedVersion({
connectRequests,
disconnectRequests,
attributeRequests,
attributeUpdates,
serverSideRpc
}),
mapping: MqttVersionMappingUtil.mapMappingToUpgradedVersion((this.connector.configurationJson as MQTTLegacyBasicConfig).mapping),
};
this.mqttRequestTypeKeys.forEach((key: RequestType) => {
const { [key]: removedKey, ...rest } = configurationJson as MQTTLegacyBasicConfig;
configurationJson = { ...rest } as any;
});
this.cleanUpConfigJson(configurationJson as MQTTBasicConfig_v3_5_2);
return configurationJson as MQTTBasicConfig;
}
getDowngradedVersion(): MQTTLegacyBasicConfig {
const { requestsMapping, mapping, ...restConfig } = this.connector.configurationJson as MQTTBasicConfig_v3_5_2;
const updatedRequestsMapping =
MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record<RequestType, RequestMappingData[]>);
const updatedMapping = MqttVersionMappingUtil.mapMappingToDowngradedVersion(mapping);
return {
...restConfig,
...updatedRequestsMapping,
mapping: updatedMapping,
};
}
private cleanUpConfigJson(configurationJson: MQTTBasicConfig_v3_5_2): void {
if (isEqual(configurationJson.requestsMapping, {})) {
delete configurationJson.requestsMapping;
}
if (isEqual(configurationJson.mapping, [])) {
delete configurationJson.mapping;
}
}
}

View File

@ -17,24 +17,23 @@
import { ControlValueAccessor, FormBuilder, FormGroup, ValidationErrors, Validator } from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { isObject } from 'lodash';
import {
MappingType,
MQTTBasicConfig,
MQTTLegacyBasicConfig,
RequestMappingData,
RequestMappingValue,
RequestType
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { Directive, OnDestroy } from '@angular/core';
import { isObject } from '@core/utils';
@Directive()
export abstract class AbstractMqttBasicConfigComponent implements ControlValueAccessor, Validator, OnDestroy {
export abstract class AbstractMqttBasicConfigComponent<BasicConfig> implements ControlValueAccessor, Validator, OnDestroy {
basicFormGroup: FormGroup;
mappingTypes = MappingType;
private destroy$ = new Subject<void>();
private onChange: (value: MQTTBasicConfig | MQTTLegacyBasicConfig) => void;
private onChange: (value: BasicConfig) => void;
private onTouched: () => void;
constructor(protected fb: FormBuilder) {
@ -58,7 +57,7 @@ export abstract class AbstractMqttBasicConfigComponent implements ControlValueAc
this.destroy$.complete();
}
registerOnChange(fn: (value: MQTTBasicConfig | MQTTLegacyBasicConfig) => void): void {
registerOnChange(fn: (value: BasicConfig) => void): void {
this.onChange = fn;
}
@ -102,6 +101,6 @@ export abstract class AbstractMqttBasicConfigComponent implements ControlValueAc
});
}
abstract writeValue(basicConfig: MQTTBasicConfig | MQTTLegacyBasicConfig): void;
protected abstract getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig | MQTTLegacyBasicConfig;
abstract writeValue(basicConfig: BasicConfig): void;
protected abstract getMappedMQTTConfig(basicConfig: MQTTBasicConfig): BasicConfig;
}

View File

@ -17,7 +17,7 @@
import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import {
MQTTBasicConfig,
MQTTBasicConfig_v3_5_2,
RequestMappingData,
RequestMappingValue,
RequestType
@ -68,12 +68,12 @@ import {
MappingTableComponent,
],
})
export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent {
export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent<MQTTBasicConfig_v3_5_2> {
@Input()
generalTabContent: TemplateRef<any>;
writeValue(basicConfig: MQTTBasicConfig): void {
writeValue(basicConfig: MQTTBasicConfig_v3_5_2): void {
const { broker, mapping = [], requestsMapping } = basicConfig;
const editedBase = {
workers: broker && (broker.maxNumberOfWorkers || broker.maxMessageNumberPerWorker) ? {
@ -88,7 +88,7 @@ export class MqttBasicConfigComponent extends AbstractMqttBasicConfigComponent {
this.basicFormGroup.setValue(editedBase, {emitEvent: false});
}
protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTBasicConfig {
protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig_v3_5_2): MQTTBasicConfig_v3_5_2 {
let { broker, workers, mapping, requestsMapping } = basicConfig || {};
if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) {

View File

@ -17,7 +17,7 @@
import { Component, forwardRef, Input, TemplateRef, ChangeDetectionStrategy } from '@angular/core';
import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
import {
MQTTBasicConfig,
MQTTBasicConfig_v3_5_2,
MQTTLegacyBasicConfig,
RequestMappingData,
RequestMappingValue,
@ -70,7 +70,7 @@ import {
MappingTableComponent,
],
})
export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigComponent {
export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigComponent<MQTTLegacyBasicConfig> {
@Input()
generalTabContent: TemplateRef<any>;
@ -85,7 +85,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo
attributeUpdates = [],
serverSideRpc = []
} = basicConfig;
const updatedRequestMapping = MqttVersionMappingUtil.mapRequestsToNewestVersion({
const updatedRequestMapping = MqttVersionMappingUtil.mapRequestsToUpgradedVersion({
connectRequests,
disconnectRequests,
attributeRequests,
@ -97,7 +97,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo
maxNumberOfWorkers: broker.maxNumberOfWorkers,
maxMessageNumberPerWorker: broker.maxMessageNumberPerWorker,
} : {},
mapping: MqttVersionMappingUtil.mapMappingToNewestVersion(mapping) || [],
mapping: MqttVersionMappingUtil.mapMappingToUpgradedVersion(mapping) || [],
broker: broker || {},
requestsMapping: this.getRequestDataArray(updatedRequestMapping),
};
@ -105,7 +105,7 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo
this.basicFormGroup.setValue(editedBase, {emitEvent: false});
}
protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig): MQTTLegacyBasicConfig {
protected getMappedMQTTConfig(basicConfig: MQTTBasicConfig_v3_5_2): MQTTLegacyBasicConfig {
let { broker, workers, mapping, requestsMapping } = basicConfig || {};
if (isDefinedAndNotNull(workers.maxNumberOfWorkers) || isDefinedAndNotNull(workers.maxMessageNumberPerWorker)) {
@ -121,8 +121,8 @@ export class MqttLegacyBasicConfigComponent extends AbstractMqttBasicConfigCompo
return {
broker,
mapping: MqttVersionMappingUtil.mapMappingToLegacyVersion(mapping),
...(MqttVersionMappingUtil.mapRequestsToLegacyVersion(requestsMapping as Record<RequestType, RequestMappingData[]>))
mapping: MqttVersionMappingUtil.mapMappingToDowngradedVersion(mapping),
...(MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record<RequestType, RequestMappingData[]>))
};
}
}

View File

@ -97,8 +97,15 @@ export class AddConnectorDialogComponent
this.submitted = true;
const value = this.connectorForm.getRawValue();
if (value.useDefaults) {
this.getDefaultConfig(value.type).subscribe(({current, legacy, ...defaultConfig}: GatewayVersionedDefaultConfig) => {
value.configurationJson = (this.data.gatewayVersion ? current : legacy) ?? defaultConfig;
this.getDefaultConfig(value.type).subscribe((defaultConfig: GatewayVersionedDefaultConfig) => {
const gatewayVersion = this.data.gatewayVersion;
if (gatewayVersion) {
value.configVersion = gatewayVersion;
}
value.configurationJson = (gatewayVersion
? defaultConfig[this.data.gatewayVersion]
: defaultConfig.legacy)
?? defaultConfig;
if (this.connectorForm.valid) {
this.dialogRef.close(value);
}

View File

@ -65,7 +65,9 @@ import { AddConnectorDialogComponent } from '@home/components/widget/lib/gateway
import { debounceTime, filter, switchMap, take, takeUntil, tap } from 'rxjs/operators';
import { ErrorStateMatcher } from '@angular/material/core';
import { PageData } from '@shared/models/page/page-data';
import { GatewayConnectorVersionMappingUtil } from './utils/gateway-connector-version-mapping.util';
import {
GatewayConnectorVersionMappingUtil
} from '@home/components/widget/lib/gateway/utils/gateway-connector-version-mapping.util';
export class ForceErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null): boolean {
@ -247,7 +249,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
value.ts = Date.now();
return GatewayConnectorVersionMappingUtil.getMappedByVersion(value, this.gatewayVersion);
return value;
}
private updateData(reload: boolean = false): void {
@ -741,7 +743,7 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
...connector,
};
connectorState.basicConfig = connectorState.configurationJson;
connectorState.basicConfig = GatewayConnectorVersionMappingUtil.getConfig(connectorState, this.gatewayVersion);
this.initialConnector = connectorState;
this.updateConnector(connectorState);
}

View File

@ -124,21 +124,14 @@ export interface GatewayConnectorBase {
configVersion?: string;
}
export type GatewayConnector = CurrentGatewayConnector | LegacyGatewayConnector;
export interface CurrentGatewayConnector extends GatewayConnectorBase {
export interface GatewayConnector extends GatewayConnectorBase {
configurationJson: ConnectorBaseConfig;
basicConfig?: ConnectorBaseConfig;
}
export interface LegacyGatewayConnector extends GatewayConnectorBase {
configurationJson: ConnectorLegacyBaseConfig;
basicConfig?: ConnectorLegacyBaseConfig;
}
export interface GatewayVersionedDefaultConfig {
legacy: LegacyGatewayConnector;
current: GatewayConnector;
legacy: GatewayConnector;
'3.5.1': GatewayConnector;
}
export interface DataMapping {
@ -201,8 +194,6 @@ export type ConnectorMappingFormValue = DeviceConnectorMapping | RequestMappingF
export type ConnectorBaseConfig = ConnectorBaseInfo | MQTTBasicConfig | OPCBasicConfig | ModbusBasicConfig;
export type ConnectorLegacyBaseConfig = ConnectorBaseInfo | MQTTLegacyBasicConfig;
export interface ConnectorBaseInfo {
name: string;
id: string;
@ -210,7 +201,9 @@ export interface ConnectorBaseInfo {
logLevel: GatewayLogLevel;
}
export interface MQTTBasicConfig {
export type MQTTBasicConfig = MQTTBasicConfig_v3_5_2 | MQTTLegacyBasicConfig;
export interface MQTTBasicConfig_v3_5_2 {
mapping: ConverterConnectorMapping[];
requestsMapping: Record<RequestType, RequestMappingData[] | RequestMappingValue[]> | RequestMappingData[] | RequestMappingValue[];
broker: BrokerConfig;

View File

@ -15,52 +15,20 @@
///
import {
ConnectorBaseConfig,
ConnectorType,
GatewayConnector,
LegacyGatewayConnector,
} from '@home/components/widget/lib/gateway/gateway-widget.models';
import { MqttVersionMappingUtil } from './mqtt-version-mapping.util';
import { MqttVersionProcessor } from '@home/components/widget/lib/gateway/abstract/mqtt-version-processor.abstract';
export class GatewayConnectorVersionMappingUtil {
export abstract class GatewayConnectorVersionMappingUtil {
static getMappedByVersion(connector: GatewayConnector, gatewayVersion: string): GatewayConnector {
static getConfig(connector: GatewayConnector, gatewayVersion: string): ConnectorBaseConfig {
switch(connector.type) {
case ConnectorType.MQTT:
return this.getMappedMQTTByVersion(connector, gatewayVersion);
return new MqttVersionProcessor(gatewayVersion, connector).getProcessedByVersion();
default:
return connector;
return connector.configurationJson as ConnectorBaseConfig;
}
}
private static getMappedMQTTByVersion(
connector: GatewayConnector | LegacyGatewayConnector,
gatewayVersion: string
): GatewayConnector | LegacyGatewayConnector {
if (this.isVersionUpdateNeeded(gatewayVersion, connector.configVersion)) {
return this.isGatewayOutdated(gatewayVersion, connector.configVersion)
? MqttVersionMappingUtil.getLegacyVersion(connector)
: MqttVersionMappingUtil.getNewestVersion(connector);
}
return connector;
}
private static isGatewayOutdated(gatewayVersion: string, configVersion: string): boolean {
if (!gatewayVersion || !configVersion) {
return false;
}
return this.parseVersion(configVersion) > this.parseVersion(gatewayVersion);
}
private static isVersionUpdateNeeded(configVersion: string, gatewayVersion: string): boolean {
if (!gatewayVersion || !configVersion) {
return false;
}
return this.parseVersion(configVersion) !== this.parseVersion(gatewayVersion);
}
private static parseVersion(version: string): number {
return Number(version?.replace(/\./g, ''));
}
}

View File

@ -14,21 +14,16 @@
/// limitations under the License.
///
import { deleteNullProperties, isEqual } from '@core/utils';
import { deleteNullProperties } from '@core/utils';
import {
AttributeRequest,
ConnectorDeviceInfo,
Converter,
ConverterConnectorMapping,
ConvertorType,
CurrentGatewayConnector,
GatewayConnector,
LegacyConverter,
LegacyConverterConnectorMapping,
LegacyGatewayConnector,
LegacyRequestMappingData,
MQTTBasicConfig,
MQTTLegacyBasicConfig,
RequestMappingData,
RequestType,
ServerSideRpc,
@ -44,56 +39,9 @@ export class MqttVersionMappingUtil {
static readonly mqttRequestMappingNewFields =
['attributeNameExpressionSource', 'responseTopicQoS', 'extensionConfig'];
static getNewestVersion(mqttConnector: GatewayConnector): CurrentGatewayConnector {
const {
connectRequests,
disconnectRequests,
attributeRequests,
attributeUpdates,
serverSideRpc
} = mqttConnector.configurationJson as MQTTLegacyBasicConfig;
let configurationJson = {
...mqttConnector.configurationJson,
requestsMapping: this.mapRequestsToNewestVersion({
connectRequests,
disconnectRequests,
attributeRequests,
attributeUpdates,
serverSideRpc
}),
mapping: this.mapMappingToNewestVersion((mqttConnector.configurationJson as MQTTLegacyBasicConfig).mapping),
};
this.mqttRequestTypeKeys.forEach((key: RequestType) => {
const { [key]: removedKey, ...rest } = configurationJson as MQTTLegacyBasicConfig;
configurationJson = { ...rest } as any;
});
this.cleanUpConfigJson(configurationJson as MQTTBasicConfig);
return {
...mqttConnector,
configurationJson
} as CurrentGatewayConnector;
}
static getLegacyVersion(mqttConnector: GatewayConnector): LegacyGatewayConnector {
const { requestsMapping, mapping, ...restConfig } = mqttConnector.configurationJson as MQTTBasicConfig;
const updatedRequestsMapping = this.mapRequestsToLegacyVersion(requestsMapping as Record<RequestType, RequestMappingData[]>);
const updatedMapping = this.mapMappingToLegacyVersion(mapping);
return {
...mqttConnector,
configurationJson: {
...restConfig,
...updatedRequestsMapping,
mapping: updatedMapping,
},
} as LegacyGatewayConnector;
}
static mapMappingToNewestVersion(mapping: LegacyConverterConnectorMapping[] | ConverterConnectorMapping[]): ConverterConnectorMapping[] {
static mapMappingToUpgradedVersion(
mapping: LegacyConverterConnectorMapping[] | ConverterConnectorMapping[]
): ConverterConnectorMapping[] {
return mapping?.map(({ converter, topicFilter, subscriptionQos = 1 }) => {
const deviceInfo = converter.deviceInfo ?? this.extractConverterDeviceInfo(converter);
@ -109,7 +57,7 @@ export class MqttVersionMappingUtil {
});
}
static mapRequestsToNewestVersion(
static mapRequestsToUpgradedVersion(
requestMapping: Record<RequestType,
RequestMappingData[] | LegacyRequestMappingData[]>
): Record<RequestType, RequestMappingData[]> {
@ -119,7 +67,7 @@ export class MqttVersionMappingUtil {
}
acc[key] = requestMapping[key].map(value => {
const newValue = this.mapRequestToNewest(value as LegacyRequestMappingData, key);
const newValue = this.mapRequestToUpgradedVersion(value as LegacyRequestMappingData, key);
this.cleanUpOldFields(newValue as {});
@ -130,7 +78,7 @@ export class MqttVersionMappingUtil {
}, {}) as Record<RequestType, RequestMappingData[]>;
}
static mapRequestsToLegacyVersion(
static mapRequestsToDowngradedVersion(
requestsMapping: Record<RequestType, RequestMappingData[]>
): Record<RequestType, LegacyRequestMappingData[]> {
return this.mqttRequestTypeKeys.reduce((acc, key) => {
@ -161,11 +109,11 @@ export class MqttVersionMappingUtil {
}, {}) as Record<RequestType, LegacyRequestMappingData[]>;
}
static mapMappingToLegacyVersion(
static mapMappingToDowngradedVersion(
mapping: ConverterConnectorMapping[]
): LegacyConverterConnectorMapping[] {
return mapping?.map((converterMapping: ConverterConnectorMapping) => {
const converter = this.mapConverterToLegacy(converterMapping.converter);
const converter = this.mapConverterToDowngradedVersion(converterMapping.converter);
this.cleanUpNewFields(converter as {});
@ -173,7 +121,7 @@ export class MqttVersionMappingUtil {
});
}
private static mapConverterToLegacy(converter: Converter): LegacyConverter {
private static mapConverterToDowngradedVersion(converter: Converter): LegacyConverter {
const { deviceInfo, ...restConverter } = converter;
return converter.type !== ConvertorType.BYTES ? {
@ -216,16 +164,6 @@ export class MqttVersionMappingUtil {
return SourceType.CONST;
}
private static cleanUpConfigJson(configurationJson: MQTTBasicConfig): void {
if (isEqual(configurationJson.requestsMapping, {})) {
delete configurationJson.requestsMapping;
}
if (isEqual(configurationJson.mapping, [])) {
delete configurationJson.mapping;
}
}
private static extractConverterDeviceInfo(converter: LegacyConverter): ConnectorDeviceInfo {
const deviceNameExpression = converter.deviceNameExpression
|| converter.deviceNameJsonExpression
@ -250,7 +188,7 @@ export class MqttVersionMappingUtil {
} : null;
}
private static mapRequestToNewest(value, key: RequestType): RequestMappingData {
private static mapRequestToUpgradedVersion(value, key: RequestType): RequestMappingData {
const deviceNameExpression = value.deviceNameJsonExpression || value.deviceNameTopicExpression || null;
const deviceProfileExpression = value.deviceTypeTopicExpression || value.deviceTypeJsonExpression || 'default';
const deviceProfileExpressionSource = deviceProfileExpression ? this.getTypeSourceByValue(deviceProfileExpression) : null;

View File

@ -1,5 +1,5 @@
{
"current": {
"3.5.1": {
"broker": {
"host": "127.0.0.1",
"port": 1883,