Merge pull request #3749 from vvlladd28/improvement/device-profile/protobuf

UI: Refactoring device-profile payload type protobuf; Refactoring view
This commit is contained in:
Igor Kulikov 2020-11-18 13:45:51 +02:00 committed by GitHub
commit 9e8e46f139
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 123 additions and 117 deletions

View File

@ -88,7 +88,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
this.displayTransportConfiguration = entity && entity.transportType &&
deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
type: entity?.provisionType ? entity?.provisionType : DeviceProvisionType.DISABLED,
type: entity?.provisionType ? entity.provisionType : DeviceProvisionType.DISABLED,
provisionDeviceKey: entity?.provisionDeviceKey,
provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
};
@ -162,7 +162,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
this.displayTransportConfiguration = entity.transportType &&
deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
type: entity?.provisionType ? entity?.provisionType : DeviceProvisionType.DISABLED,
type: entity?.provisionType ? entity.provisionType : DeviceProvisionType.DISABLED,
provisionDeviceKey: entity?.provisionDeviceKey,
provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
};

View File

@ -16,86 +16,80 @@
-->
<form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;">
<section formGroupName="configuration">
<fieldset class="fields-group">
<legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend>
<div fxLayoutGap="8px" fxLayout="column">
<div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column">
<mat-form-field fxFlex>
<mat-label translate>device-profile.telemetry-topic-filter</mat-label>
<input matInput required
formControlName="deviceTelemetryTopic"
type="text">
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('required')">
{{ 'device-profile.telemetry-topic-filter-required' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('invalidSingleTopicCharacter')">
{{ 'device-profile.not-valid-single-character' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('invalidMultiTopicCharacter')">
{{ 'device-profile.not-valid-multi-character' | translate}}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label translate>device-profile.attributes-topic-filter</mat-label>
<input matInput required
formControlName="deviceAttributesTopic"
type="text">
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('required')">
{{ 'device-profile.attributes-topic-filter-required' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('invalidSingleTopicCharacter')">
{{ 'device-profile.not-valid-single-character' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('invalidMultiTopicCharacter')">
{{ 'device-profile.not-valid-multi-character' | translate}}
</mat-error>
</mat-form-field>
</div>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.hasError('unique')">
{{ 'device-profile.mqtt-device-topic-filters-unique' | translate }}
</mat-error>
<div class="tb-hint" innerHTML="{{ 'device-profile.support-level-wildcards' | translate }}"></div>
<div class="tb-hint" innerHTML="{{ 'device-profile.single-level-wildcards-hint' | translate }}"></div>
<div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div>
</div>
</fieldset>
<section formGroupName="transportPayloadTypeConfiguration">
<fieldset class="fields-group">
<legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend>
<legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend>
<div fxLayoutGap="8px" fxLayout="column">
<div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column">
<mat-form-field class="mat-block">
<mat-select formControlName="transportPayloadType" required>
<mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">
{{mqttTransportPayloadTypeTranslations.get(type) | translate}}
</mat-option>
</mat-select>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').hasError('required')">
{{ 'device-profile.mqtt-payload-type-required' | translate }}
</mat-error>
</mat-form-field>
<div *ngIf="protoPayloadType" fxLayout="column">
<mat-form-field fxFlex>
<mat-label translate>device-profile.telemetry-topic-filter</mat-label>
<input matInput required
formControlName="deviceTelemetryTopic"
type="text">
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('required')">
{{ 'device-profile.telemetry-topic-filter-required' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('invalidSingleTopicCharacter')">
{{ 'device-profile.not-valid-single-character' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('invalidMultiTopicCharacter')">
{{ 'device-profile.not-valid-multi-character' | translate}}
<mat-label translate>device-profile.telemetry-proto-schema</mat-label>
<textarea matInput required formControlName="deviceTelemetryProtoSchema" rows="5"></textarea>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')">
{{ 'device-profile.telemetry-proto-schema-required' | translate}}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label translate>device-profile.attributes-topic-filter</mat-label>
<input matInput required
formControlName="deviceAttributesTopic"
type="text">
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('required')">
{{ 'device-profile.attributes-topic-filter-required' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('invalidSingleTopicCharacter')">
{{ 'device-profile.not-valid-single-character' | translate}}
</mat-error>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('invalidMultiTopicCharacter')">
{{ 'device-profile.not-valid-multi-character' | translate}}
<mat-label translate>device-profile.attributes-proto-schema</mat-label>
<textarea matInput required formControlName="deviceAttributesProtoSchema" rows="5"></textarea>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')">
{{ 'device-profile.attributes-proto-schema-required' | translate}}
</mat-error>
</mat-form-field>
</div>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration').hasError('unique')">
{{ 'device-profile.mqtt-device-topic-filters-unique' | translate }}
</mat-error>
<div class="tb-hint" innerHTML="{{ 'device-profile.support-level-wildcards' | translate }}"></div>
<div class="tb-hint" innerHTML="{{ 'device-profile.single-level-wildcards-hint' | translate }}"></div>
<div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div>
</div>
</fieldset>
<section formGroupName="transportPayloadTypeConfiguration">
<fieldset class="fields-group">
<legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend>
<div fxLayoutGap="8px" fxLayout="column">
<mat-form-field class="mat-block">
<mat-select formControlName="transportPayloadType" required>
<mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">
{{mqttTransportPayloadTypeTranslations.get(type) | translate}}
</mat-option>
</mat-select>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').hasError('required')">
{{ 'device-profile.mqtt-payload-type-required' | translate }}
</mat-error>
</mat-form-field>
<div *ngIf="protoPayloadType" fxLayout="column">
<mat-form-field fxFlex>
<mat-label translate>device-profile.telemetry-proto-schema</mat-label>
<textarea matInput required
formControlName="deviceTelemetryProtoSchema"
rows="5"></textarea>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')">
{{ 'device-profile.telemetry-proto-schema-required' | translate}}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label translate>device-profile.attributes-proto-schema</mat-label>
<textarea matInput required
formControlName="deviceAttributesProtoSchema"
rows="5"></textarea>
<mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')">
{{ 'device-profile.attributes-proto-schema-required' | translate}}
</mat-error>
</mat-form-field>
</div>
</div>
</fieldset>
</section>
</section>
</form>

View File

@ -54,6 +54,34 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
mqttDeviceProfileTransportConfigurationFormGroup: FormGroup;
private defaultTelemetrySchema =
'syntax ="proto3";\n' +
'package telemetry;\n' +
'\n' +
'message SensorDataReading {\n' +
'\n' +
' double temperature = 1;\n' +
' double humidity = 2;\n' +
' InnerObject innerObject = 3;\n' +
'\n' +
' message InnerObject {\n' +
' string key1 = 1;\n' +
' bool key2 = 2;\n' +
' double key3 = 3;\n' +
' int32 key4 = 4;\n' +
' string key5 = 5;\n' +
' }\n' +
'}\n';
private defaultAttributesSchema =
'syntax ="proto3";\n' +
'package attributes;\n' +
'\n' +
'message SensorConfiguration {\n' +
' string firmwareVersion = 1;\n' +
' string serialNumber = 2;\n' +
'}';
private requiredValue: boolean;
get required(): boolean {
@ -83,17 +111,18 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
ngOnInit() {
this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({
configuration: this.fb.group({
deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]],
deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]],
transportPayloadTypeConfiguration: this.fb.group({
transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required]
transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required],
deviceTelemetryProtoSchema: [this.defaultTelemetrySchema, Validators.required],
deviceAttributesProtoSchema: [this.defaultAttributesSchema, Validators.required]
})
}, {validator: this.uniqueDeviceTopicValidator})
});
this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').valueChanges.subscribe(payloadType => {
this.updateTransportPayloadBasedControls(payloadType);
this.mqttDeviceProfileTransportConfigurationFormGroup.updateValueAndValidity();
}, {validator: this.uniqueDeviceTopicValidator}
);
this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType')
.valueChanges.subscribe(payloadType => {
this.updateTransportPayloadBasedControls(payloadType, true);
});
this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => {
this.updateModel();
@ -110,58 +139,41 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
}
get protoPayloadType(): boolean {
let transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').value;
const transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').value;
return transportPayloadType === MqttTransportPayloadType.PROTOBUF;
}
writeValue(value: MqttDeviceProfileTransportConfiguration | null): void {
if (isDefinedAndNotNull(value)) {
this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration.transportPayloadType);
this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false});
this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration?.transportPayloadType);
}
}
private updateModel() {
let configuration: DeviceProfileTransportConfiguration = null;
if (this.mqttDeviceProfileTransportConfigurationFormGroup.valid) {
configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.getRawValue().configuration;
configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.value;
configuration.type = DeviceTransportType.MQTT;
}
this.propagateChange(configuration);
}
private updateTransportPayloadBasedControls(type: MqttTransportPayloadType) {
const transportPayloadTypeConfigurationFormGroup = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration') as FormGroup;
if (type === MqttTransportPayloadType.PROTOBUF) {
const defaultTelemetrySchema = "syntax =\"proto3\";\n" +
"package telemetry;\n" +
"\n" +
"message SensorDataReading {\n" +
"\n" +
" double temperature = 1;\n" +
" double humidity = 2;\n" +
" InnerObject innerObject = 3;\n" +
"\n" +
" message InnerObject {\n" +
" string key1 = 1;\n" +
" bool key2 = 2;\n" +
" double key3 = 3;\n" +
" int32 key4 = 4;\n" +
" string key5 = 5;\n" +
" }\n" +
"}\n";
const defaultAttributesSchema = "syntax =\"proto3\";\n" +
"package attributes;\n" +
"\n" +
"message SensorConfiguration {\n" +
" string firmwareVersion = 1;\n" +
" string serialNumber = 2;\n" +
"}";
transportPayloadTypeConfigurationFormGroup.registerControl('deviceTelemetryProtoSchema', this.fb.control(defaultTelemetrySchema, Validators.required));
transportPayloadTypeConfigurationFormGroup.registerControl('deviceAttributesProtoSchema', this.fb.control(defaultAttributesSchema, Validators.required));
private updateTransportPayloadBasedControls(type: MqttTransportPayloadType, forceUpdated = false) {
const transportPayloadTypeForm = this.mqttDeviceProfileTransportConfigurationFormGroup
.get('transportPayloadTypeConfiguration') as FormGroup;
if (forceUpdated) {
transportPayloadTypeForm.patchValue({
deviceTelemetryProtoSchema: this.defaultTelemetrySchema,
deviceAttributesProtoSchema: this.defaultAttributesSchema
}, {emitEvent: false});
}
if (type === MqttTransportPayloadType.PROTOBUF && !this.disabled) {
transportPayloadTypeForm.get('deviceTelemetryProtoSchema').enable({emitEvent: false});
transportPayloadTypeForm.get('deviceAttributesProtoSchema').enable({emitEvent: false});
} else {
transportPayloadTypeConfigurationFormGroup.removeControl('deviceTelemetryProtoSchema');
transportPayloadTypeConfigurationFormGroup.removeControl('deviceAttributesProtoSchema');
transportPayloadTypeForm.get('deviceTelemetryProtoSchema').disable({emitEvent: false});
transportPayloadTypeForm.get('deviceAttributesProtoSchema').disable({emitEvent: false});
}
}

View File

@ -41,9 +41,9 @@
</div>
</mat-tab>
<mat-tab *ngIf="entity"
label="{{'device-profile.alarm-rules' | translate:
{count: entity.profileData.alarms && entity.profileData.alarms.length ?
entity.profileData.alarms.length : 0} }}" #alarmRules="matTab">
label="{{'device-profile.alarm-rules-with-count' | translate:
{count: entity.profileData?.alarms?.length ? entity.profileData.alarms.length : 0}
}}" #alarmRules="matTab">
<div class="mat-padding" [formGroup]="detailsForm">
<div formGroupName="profileData">
<tb-device-profile-alarms formControlName="alarms"></tb-device-profile-alarms>