Merge pull request #11656 from maxunbearable/fix/4413-gateway-fixes
Gateway UI improvements and minor bug fixes
This commit is contained in:
commit
8a5cc8cad5
@ -74,8 +74,8 @@ export class MqttVersionProcessor extends GatewayConnectorVersionProcessor<MQTTB
|
|||||||
getDowngradedVersion(): GatewayConnector<MQTTLegacyBasicConfig> {
|
getDowngradedVersion(): GatewayConnector<MQTTLegacyBasicConfig> {
|
||||||
const { requestsMapping, mapping, ...restConfig } = this.connector.configurationJson as MQTTBasicConfig_v3_5_2;
|
const { requestsMapping, mapping, ...restConfig } = this.connector.configurationJson as MQTTBasicConfig_v3_5_2;
|
||||||
|
|
||||||
const updatedRequestsMapping =
|
const updatedRequestsMapping = requestsMapping
|
||||||
MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record<RequestType, RequestMappingData[]>);
|
? MqttVersionMappingUtil.mapRequestsToDowngradedVersion(requestsMapping as Record<RequestType, RequestMappingData[]>) : {};
|
||||||
const updatedMapping = MqttVersionMappingUtil.mapMappingToDowngradedVersion(mapping);
|
const updatedMapping = MqttVersionMappingUtil.mapMappingToDowngradedVersion(mapping);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import { Subject } from 'rxjs';
|
|||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { SharedModule } from '@shared/shared.module';
|
import { SharedModule } from '@shared/shared.module';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { GatewayConfigValue } from '@home/components/widget/lib/gateway/configuration/models/gateway-configuration.models';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-gateway-advanced-configuration',
|
selector: 'tb-gateway-advanced-configuration',
|
||||||
@ -83,8 +84,8 @@ export class GatewayAdvancedConfigurationComponent implements OnDestroy, Control
|
|||||||
this.onTouched = fn;
|
this.onTouched = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(basicConfig: unknown): void {
|
writeValue(advancedConfig: GatewayConfigValue): void {
|
||||||
this.advancedFormControl.reset(basicConfig, {emitEvent: false});
|
this.advancedFormControl.reset(advancedConfig, {emitEvent: false});
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(): ValidationErrors | null {
|
validate(): ValidationErrors | null {
|
||||||
|
|||||||
@ -640,10 +640,11 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
<button mat-icon-button (click)="removeCommandControl($index, $event)"
|
<button mat-icon-button (click)="removeCommandControl($index, $event)"
|
||||||
|
class="tb-box-button"
|
||||||
[disabled]="!basicFormGroup.get('thingsboard.remoteConfiguration').value"
|
[disabled]="!basicFormGroup.get('thingsboard.remoteConfiguration').value"
|
||||||
matTooltip="{{ 'gateway.statistics.remove' | translate }}"
|
matTooltip="{{ 'gateway.statistics.remove' | translate }}"
|
||||||
matTooltipPosition="above">
|
matTooltipPosition="above">
|
||||||
<mat-icon>close</mat-icon>
|
<mat-icon>delete</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button mat-stroked-button color="primary"
|
<button mat-stroked-button color="primary"
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import {
|
|||||||
FormGroup,
|
FormGroup,
|
||||||
} from '@angular/forms';
|
} from '@angular/forms';
|
||||||
import { EntityId } from '@shared/models/id/entity-id';
|
import { EntityId } from '@shared/models/id/entity-id';
|
||||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
import { AttributeService } from '@core/http/attribute.service';
|
import { AttributeService } from '@core/http/attribute.service';
|
||||||
import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetry.models';
|
import { AttributeData, AttributeScope } from '@shared/models/telemetry/telemetry.models';
|
||||||
import { DeviceService } from '@core/http/device.service';
|
import { DeviceService } from '@core/http/device.service';
|
||||||
@ -40,7 +40,9 @@ import {
|
|||||||
GatewayConfigSecurity,
|
GatewayConfigSecurity,
|
||||||
GatewayConfigValue,
|
GatewayConfigValue,
|
||||||
GatewayGeneralConfig,
|
GatewayGeneralConfig,
|
||||||
|
GatewayGRPCConfig,
|
||||||
GatewayLogsConfig,
|
GatewayLogsConfig,
|
||||||
|
GatewayStorageConfig,
|
||||||
LocalLogs,
|
LocalLogs,
|
||||||
LogAttribute,
|
LogAttribute,
|
||||||
LogConfig,
|
LogConfig,
|
||||||
@ -113,7 +115,7 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
|
|||||||
this.gatewayConfigGroup.get('basicConfig').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
|
this.gatewayConfigGroup.get('basicConfig').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
|
||||||
const advancedControl = this.gatewayConfigGroup.get('advancedConfig');
|
const advancedControl = this.gatewayConfigGroup.get('advancedConfig');
|
||||||
|
|
||||||
if (!isEqual(advancedControl.value, value)) {
|
if (!isEqual(advancedControl.value, value) && this.gatewayConfigGroup.get('mode').value === ConfigurationModes.BASIC) {
|
||||||
advancedControl.patchValue(value, {emitEvent: false});
|
advancedControl.patchValue(value, {emitEvent: false});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -121,7 +123,7 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
|
|||||||
this.gatewayConfigGroup.get('advancedConfig').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
|
this.gatewayConfigGroup.get('advancedConfig').valueChanges.pipe(takeUntil(this.destroy$)).subscribe(value => {
|
||||||
const basicControl = this.gatewayConfigGroup.get('basicConfig');
|
const basicControl = this.gatewayConfigGroup.get('basicConfig');
|
||||||
|
|
||||||
if (!isEqual(basicControl.value, value)) {
|
if (!isEqual(basicControl.value, value) && this.gatewayConfigGroup.get('mode').value === ConfigurationModes.ADVANCED) {
|
||||||
basicControl.patchValue(value, {emitEvent: false});
|
basicControl.patchValue(value, {emitEvent: false});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -320,10 +322,10 @@ export class GatewayConfigurationComponent implements AfterViewInit, OnDestroy {
|
|||||||
|
|
||||||
private updateConfigs(attributes: AttributeData[]): void {
|
private updateConfigs(attributes: AttributeData[]): void {
|
||||||
const formValue: GatewayConfigValue = {
|
const formValue: GatewayConfigValue = {
|
||||||
thingsboard: null,
|
thingsboard: {} as GatewayGeneralConfig,
|
||||||
grpc: null,
|
grpc: {} as GatewayGRPCConfig,
|
||||||
logs: null,
|
logs: {} as GatewayLogsConfig,
|
||||||
storage: null,
|
storage: {} as GatewayStorageConfig,
|
||||||
mode: ConfigurationModes.BASIC
|
mode: ConfigurationModes.BASIC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -27,32 +27,36 @@ import { GatewayLogLevel } from '@home/components/widget/lib/gateway/gateway-for
|
|||||||
export interface GatewayConfigValue {
|
export interface GatewayConfigValue {
|
||||||
mode: ConfigurationModes;
|
mode: ConfigurationModes;
|
||||||
thingsboard: GatewayGeneralConfig;
|
thingsboard: GatewayGeneralConfig;
|
||||||
storage: {
|
storage: GatewayStorageConfig;
|
||||||
type: StorageTypes;
|
grpc: GatewayGRPCConfig;
|
||||||
read_records_count?: number;
|
|
||||||
max_records_count?: number;
|
|
||||||
data_folder_path?: string;
|
|
||||||
max_file_count?: number;
|
|
||||||
max_read_records_count?: number;
|
|
||||||
max_records_per_file?: number;
|
|
||||||
data_file_path?: string;
|
|
||||||
messages_ttl_check_in_hours?: number;
|
|
||||||
messages_ttl_in_days?: number;
|
|
||||||
};
|
|
||||||
grpc: {
|
|
||||||
enabled: boolean;
|
|
||||||
serverPort: number;
|
|
||||||
keepAliveTimeMs: number;
|
|
||||||
keepAliveTimeoutMs: number;
|
|
||||||
keepalivePermitWithoutCalls: boolean;
|
|
||||||
maxPingsWithoutData: number;
|
|
||||||
minTimeBetweenPingsMs: number;
|
|
||||||
minPingIntervalWithoutDataMs: number;
|
|
||||||
};
|
|
||||||
connectors?: GatewayConnector[];
|
connectors?: GatewayConnector[];
|
||||||
logs: GatewayLogsConfig;
|
logs: GatewayLogsConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GatewayGRPCConfig {
|
||||||
|
enabled: boolean;
|
||||||
|
serverPort: number;
|
||||||
|
keepAliveTimeMs: number;
|
||||||
|
keepAliveTimeoutMs: number;
|
||||||
|
keepalivePermitWithoutCalls: boolean;
|
||||||
|
maxPingsWithoutData: number;
|
||||||
|
minTimeBetweenPingsMs: number;
|
||||||
|
minPingIntervalWithoutDataMs: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GatewayStorageConfig {
|
||||||
|
type: StorageTypes;
|
||||||
|
read_records_count?: number;
|
||||||
|
max_records_count?: number;
|
||||||
|
data_folder_path?: string;
|
||||||
|
max_file_count?: number;
|
||||||
|
max_read_records_count?: number;
|
||||||
|
max_records_per_file?: number;
|
||||||
|
data_file_path?: string;
|
||||||
|
messages_ttl_check_in_hours?: number;
|
||||||
|
messages_ttl_in_days?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface GatewayGeneralConfig {
|
export interface GatewayGeneralConfig {
|
||||||
host: string;
|
host: string;
|
||||||
port: number;
|
port: number;
|
||||||
|
|||||||
@ -256,10 +256,11 @@ export class MappingTableComponent implements ControlValueAccessor, Validator, A
|
|||||||
private getMappingValue(value: ConnectorMapping): MappingValue {
|
private getMappingValue(value: ConnectorMapping): MappingValue {
|
||||||
switch (this.mappingType) {
|
switch (this.mappingType) {
|
||||||
case MappingType.DATA:
|
case MappingType.DATA:
|
||||||
|
const converterType = ConvertorTypeTranslationsMap.get((value as ConverterConnectorMapping).converter?.type);
|
||||||
return {
|
return {
|
||||||
topicFilter: (value as ConverterConnectorMapping).topicFilter,
|
topicFilter: (value as ConverterConnectorMapping).topicFilter,
|
||||||
QoS: (value as ConverterConnectorMapping).subscriptionQos,
|
QoS: (value as ConverterConnectorMapping).subscriptionQos,
|
||||||
converter: this.translate.instant(ConvertorTypeTranslationsMap.get((value as ConverterConnectorMapping).converter?.type) || '')
|
converter: converterType ? this.translate.instant(converterType) : ''
|
||||||
};
|
};
|
||||||
case MappingType.REQUESTS:
|
case MappingType.REQUESTS:
|
||||||
let details: string;
|
let details: string;
|
||||||
|
|||||||
@ -54,7 +54,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div 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" tbTruncateWithTooltip translate>gateway.security</div>
|
<div class="fixed-title-width" tb-hint-tooltip-icon="{{ 'gateway.hints.security-policy' | translate }}">
|
||||||
|
<div tbTruncateWithTooltip>{{ 'gateway.security-policy' | translate }}</div>
|
||||||
|
</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">
|
||||||
<mat-select formControlName="security">
|
<mat-select formControlName="security">
|
||||||
|
|||||||
@ -297,12 +297,13 @@ export class GatewayConnectorComponent extends PageComponent implements AfterVie
|
|||||||
}
|
}
|
||||||
|
|
||||||
private hasSameConfig(sharedDataConfigJson: ConnectorBaseInfo, connectorDataConfigJson: ConnectorBaseInfo): boolean {
|
private hasSameConfig(sharedDataConfigJson: ConnectorBaseInfo, connectorDataConfigJson: ConnectorBaseInfo): boolean {
|
||||||
const { name, id, enableRemoteLogging, logLevel, ...sharedDataConfig } = sharedDataConfigJson;
|
const { name, id, enableRemoteLogging, logLevel, configVersion, ...sharedDataConfig } = sharedDataConfigJson;
|
||||||
const {
|
const {
|
||||||
name: connectorName,
|
name: connectorName,
|
||||||
id: connectorId,
|
id: connectorId,
|
||||||
enableRemoteLogging: connectorEnableRemoteLogging,
|
enableRemoteLogging: connectorEnableRemoteLogging,
|
||||||
logLevel: connectorLogLevel,
|
logLevel: connectorLogLevel,
|
||||||
|
configVersion: connectorConfigVersion,
|
||||||
...connectorConfig
|
...connectorConfig
|
||||||
} = connectorDataConfigJson;
|
} = connectorDataConfigJson;
|
||||||
|
|
||||||
|
|||||||
@ -208,6 +208,7 @@ export interface ConnectorBaseInfo {
|
|||||||
id: string;
|
id: string;
|
||||||
enableRemoteLogging: boolean;
|
enableRemoteLogging: boolean;
|
||||||
logLevel: GatewayLogLevel;
|
logLevel: GatewayLogLevel;
|
||||||
|
configVersion: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MQTTBasicConfig = MQTTBasicConfig_v3_5_2 | MQTTLegacyBasicConfig;
|
export type MQTTBasicConfig = MQTTBasicConfig_v3_5_2 | MQTTLegacyBasicConfig;
|
||||||
|
|||||||
@ -35,9 +35,10 @@ import {
|
|||||||
export class OpcVersionMappingUtil {
|
export class OpcVersionMappingUtil {
|
||||||
|
|
||||||
static mapServerToUpgradedVersion(server: LegacyServerConfig): ServerConfig {
|
static mapServerToUpgradedVersion(server: LegacyServerConfig): ServerConfig {
|
||||||
const { mapping, disableSubscriptions, ...restServer } = server;
|
const { mapping, disableSubscriptions, pollPeriodInMillis, ...restServer } = server;
|
||||||
return {
|
return {
|
||||||
...restServer,
|
...restServer,
|
||||||
|
pollPeriodInMillis: pollPeriodInMillis ?? 5000,
|
||||||
enableSubscriptions: !disableSubscriptions,
|
enableSubscriptions: !disableSubscriptions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3254,6 +3254,7 @@
|
|||||||
"sub-check-period": "Subscription check period (ms)",
|
"sub-check-period": "Subscription check period (ms)",
|
||||||
"sub-check-period-error": "Subscription check period should be at least {{min}} (ms).",
|
"sub-check-period-error": "Subscription check period should be at least {{min}} (ms).",
|
||||||
"security": "Security",
|
"security": "Security",
|
||||||
|
"security-policy": "Security policy",
|
||||||
"security-type": "Security type",
|
"security-type": "Security type",
|
||||||
"security-types": {
|
"security-types": {
|
||||||
"access-token": "Access Token",
|
"access-token": "Access Token",
|
||||||
@ -3460,6 +3461,7 @@
|
|||||||
"file": "Your data will be stored in separated files and will be saved even after the gateway restart.",
|
"file": "Your data will be stored in separated files and will be saved even after the gateway restart.",
|
||||||
"sqlite": "Your data will be stored in file based database. And will be saved even after the gateway restart.",
|
"sqlite": "Your data will be stored in file based database. And will be saved even after the gateway restart.",
|
||||||
"opc-timeout": "Timeout in milliseconds for connecting to OPC-UA server.",
|
"opc-timeout": "Timeout in milliseconds for connecting to OPC-UA server.",
|
||||||
|
"security-policy": "Security Policy defines the security mechanisms to be applied.",
|
||||||
"scan-period": "Period in milliseconds to rescan the server.",
|
"scan-period": "Period in milliseconds to rescan the server.",
|
||||||
"sub-check-period": "Period to check the subscriptions in the OPC-UA server.",
|
"sub-check-period": "Period to check the subscriptions in the OPC-UA server.",
|
||||||
"enable-subscription": "If true - the gateway will subscribe to interesting nodes and wait for data update and if false - the gateway will rescan OPC-UA server every scanPeriodInMillis.",
|
"enable-subscription": "If true - the gateway will subscribe to interesting nodes and wait for data update and if false - the gateway will rescan OPC-UA server every scanPeriodInMillis.",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user