Commit 9e8e46f139afc65e64ff1237d98c55198b7ca821

Authored by Igor Kulikov
Committed by GitHub
2 parents 1d959321 08693a40

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

UI: Refactoring device-profile payload type protobuf; Refactoring view
@@ -88,7 +88,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { @@ -88,7 +88,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
88 this.displayTransportConfiguration = entity && entity.transportType && 88 this.displayTransportConfiguration = entity && entity.transportType &&
89 deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration; 89 deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
90 const deviceProvisionConfiguration: DeviceProvisionConfiguration = { 90 const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
91 - type: entity?.provisionType ? entity?.provisionType : DeviceProvisionType.DISABLED, 91 + type: entity?.provisionType ? entity.provisionType : DeviceProvisionType.DISABLED,
92 provisionDeviceKey: entity?.provisionDeviceKey, 92 provisionDeviceKey: entity?.provisionDeviceKey,
93 provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret 93 provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
94 }; 94 };
@@ -162,7 +162,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> { @@ -162,7 +162,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
162 this.displayTransportConfiguration = entity.transportType && 162 this.displayTransportConfiguration = entity.transportType &&
163 deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration; 163 deviceTransportTypeConfigurationInfoMap.get(entity.transportType).hasProfileConfiguration;
164 const deviceProvisionConfiguration: DeviceProvisionConfiguration = { 164 const deviceProvisionConfiguration: DeviceProvisionConfiguration = {
165 - type: entity?.provisionType ? entity?.provisionType : DeviceProvisionType.DISABLED, 165 + type: entity?.provisionType ? entity.provisionType : DeviceProvisionType.DISABLED,
166 provisionDeviceKey: entity?.provisionDeviceKey, 166 provisionDeviceKey: entity?.provisionDeviceKey,
167 provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret 167 provisionDeviceSecret: entity?.profileData?.provisionConfiguration?.provisionDeviceSecret
168 }; 168 };
@@ -16,86 +16,80 @@ @@ -16,86 +16,80 @@
16 16
17 --> 17 -->
18 <form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;"> 18 <form [formGroup]="mqttDeviceProfileTransportConfigurationFormGroup" style="padding-bottom: 16px;">
19 - <section formGroupName="configuration"> 19 + <fieldset class="fields-group">
  20 + <legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend>
  21 + <div fxLayoutGap="8px" fxLayout="column">
  22 + <div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column">
  23 + <mat-form-field fxFlex>
  24 + <mat-label translate>device-profile.telemetry-topic-filter</mat-label>
  25 + <input matInput required
  26 + formControlName="deviceTelemetryTopic"
  27 + type="text">
  28 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('required')">
  29 + {{ 'device-profile.telemetry-topic-filter-required' | translate}}
  30 + </mat-error>
  31 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('invalidSingleTopicCharacter')">
  32 + {{ 'device-profile.not-valid-single-character' | translate}}
  33 + </mat-error>
  34 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceTelemetryTopic').hasError('invalidMultiTopicCharacter')">
  35 + {{ 'device-profile.not-valid-multi-character' | translate}}
  36 + </mat-error>
  37 + </mat-form-field>
  38 + <mat-form-field fxFlex>
  39 + <mat-label translate>device-profile.attributes-topic-filter</mat-label>
  40 + <input matInput required
  41 + formControlName="deviceAttributesTopic"
  42 + type="text">
  43 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('required')">
  44 + {{ 'device-profile.attributes-topic-filter-required' | translate}}
  45 + </mat-error>
  46 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('invalidSingleTopicCharacter')">
  47 + {{ 'device-profile.not-valid-single-character' | translate}}
  48 + </mat-error>
  49 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('deviceAttributesTopic').hasError('invalidMultiTopicCharacter')">
  50 + {{ 'device-profile.not-valid-multi-character' | translate}}
  51 + </mat-error>
  52 + </mat-form-field>
  53 + </div>
  54 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.hasError('unique')">
  55 + {{ 'device-profile.mqtt-device-topic-filters-unique' | translate }}
  56 + </mat-error>
  57 + <div class="tb-hint" innerHTML="{{ 'device-profile.support-level-wildcards' | translate }}"></div>
  58 + <div class="tb-hint" innerHTML="{{ 'device-profile.single-level-wildcards-hint' | translate }}"></div>
  59 + <div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div>
  60 + </div>
  61 + </fieldset>
  62 + <section formGroupName="transportPayloadTypeConfiguration">
20 <fieldset class="fields-group"> 63 <fieldset class="fields-group">
21 - <legend class="group-title" translate>device-profile.mqtt-device-topic-filters</legend> 64 + <legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend>
22 <div fxLayoutGap="8px" fxLayout="column"> 65 <div fxLayoutGap="8px" fxLayout="column">
23 - <div fxLayout="row" fxLayoutGap="8px" fxLayout.xs="column"> 66 + <mat-form-field class="mat-block">
  67 + <mat-select formControlName="transportPayloadType" required>
  68 + <mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">
  69 + {{mqttTransportPayloadTypeTranslations.get(type) | translate}}
  70 + </mat-option>
  71 + </mat-select>
  72 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').hasError('required')">
  73 + {{ 'device-profile.mqtt-payload-type-required' | translate }}
  74 + </mat-error>
  75 + </mat-form-field>
  76 + <div *ngIf="protoPayloadType" fxLayout="column">
24 <mat-form-field fxFlex> 77 <mat-form-field fxFlex>
25 - <mat-label translate>device-profile.telemetry-topic-filter</mat-label>  
26 - <input matInput required  
27 - formControlName="deviceTelemetryTopic"  
28 - type="text">  
29 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('required')">  
30 - {{ 'device-profile.telemetry-topic-filter-required' | translate}}  
31 - </mat-error>  
32 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('invalidSingleTopicCharacter')">  
33 - {{ 'device-profile.not-valid-single-character' | translate}}  
34 - </mat-error>  
35 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceTelemetryTopic').hasError('invalidMultiTopicCharacter')">  
36 - {{ 'device-profile.not-valid-multi-character' | translate}} 78 + <mat-label translate>device-profile.telemetry-proto-schema</mat-label>
  79 + <textarea matInput required formControlName="deviceTelemetryProtoSchema" rows="5"></textarea>
  80 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')">
  81 + {{ 'device-profile.telemetry-proto-schema-required' | translate}}
37 </mat-error> 82 </mat-error>
38 </mat-form-field> 83 </mat-form-field>
39 <mat-form-field fxFlex> 84 <mat-form-field fxFlex>
40 - <mat-label translate>device-profile.attributes-topic-filter</mat-label>  
41 - <input matInput required  
42 - formControlName="deviceAttributesTopic"  
43 - type="text">  
44 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('required')">  
45 - {{ 'device-profile.attributes-topic-filter-required' | translate}}  
46 - </mat-error>  
47 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('invalidSingleTopicCharacter')">  
48 - {{ 'device-profile.not-valid-single-character' | translate}}  
49 - </mat-error>  
50 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.deviceAttributesTopic').hasError('invalidMultiTopicCharacter')">  
51 - {{ 'device-profile.not-valid-multi-character' | translate}} 85 + <mat-label translate>device-profile.attributes-proto-schema</mat-label>
  86 + <textarea matInput required formControlName="deviceAttributesProtoSchema" rows="5"></textarea>
  87 + <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')">
  88 + {{ 'device-profile.attributes-proto-schema-required' | translate}}
52 </mat-error> 89 </mat-error>
53 </mat-form-field> 90 </mat-form-field>
54 </div> 91 </div>
55 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration').hasError('unique')">  
56 - {{ 'device-profile.mqtt-device-topic-filters-unique' | translate }}  
57 - </mat-error>  
58 - <div class="tb-hint" innerHTML="{{ 'device-profile.support-level-wildcards' | translate }}"></div>  
59 - <div class="tb-hint" innerHTML="{{ 'device-profile.single-level-wildcards-hint' | translate }}"></div>  
60 - <div class="tb-hint" innerHTML="{{ 'device-profile.multi-level-wildcards-hint' | translate }}"></div>  
61 </div> 92 </div>
62 </fieldset> 93 </fieldset>
63 - <section formGroupName="transportPayloadTypeConfiguration">  
64 - <fieldset class="fields-group">  
65 - <legend class="group-title" translate>device-profile.mqtt-device-payload-type</legend>  
66 - <div fxLayoutGap="8px" fxLayout="column">  
67 - <mat-form-field class="mat-block">  
68 - <mat-select formControlName="transportPayloadType" required>  
69 - <mat-option *ngFor="let type of mqttTransportPayloadTypes" [value]="type">  
70 - {{mqttTransportPayloadTypeTranslations.get(type) | translate}}  
71 - </mat-option>  
72 - </mat-select>  
73 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').hasError('required')">  
74 - {{ 'device-profile.mqtt-payload-type-required' | translate }}  
75 - </mat-error>  
76 - </mat-form-field>  
77 - <div *ngIf="protoPayloadType" fxLayout="column">  
78 - <mat-form-field fxFlex>  
79 - <mat-label translate>device-profile.telemetry-proto-schema</mat-label>  
80 - <textarea matInput required  
81 - formControlName="deviceTelemetryProtoSchema"  
82 - rows="5"></textarea>  
83 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceTelemetryProtoSchema').hasError('required')">  
84 - {{ 'device-profile.telemetry-proto-schema-required' | translate}}  
85 - </mat-error>  
86 - </mat-form-field>  
87 - <mat-form-field fxFlex>  
88 - <mat-label translate>device-profile.attributes-proto-schema</mat-label>  
89 - <textarea matInput required  
90 - formControlName="deviceAttributesProtoSchema"  
91 - rows="5"></textarea>  
92 - <mat-error *ngIf="mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.deviceAttributesProtoSchema').hasError('required')">  
93 - {{ 'device-profile.attributes-proto-schema-required' | translate}}  
94 - </mat-error>  
95 - </mat-form-field>  
96 - </div>  
97 - </div>  
98 - </fieldset>  
99 - </section>  
100 </section> 94 </section>
101 </form> 95 </form>
@@ -54,6 +54,34 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control @@ -54,6 +54,34 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
54 54
55 mqttDeviceProfileTransportConfigurationFormGroup: FormGroup; 55 mqttDeviceProfileTransportConfigurationFormGroup: FormGroup;
56 56
  57 + private defaultTelemetrySchema =
  58 + 'syntax ="proto3";\n' +
  59 + 'package telemetry;\n' +
  60 + '\n' +
  61 + 'message SensorDataReading {\n' +
  62 + '\n' +
  63 + ' double temperature = 1;\n' +
  64 + ' double humidity = 2;\n' +
  65 + ' InnerObject innerObject = 3;\n' +
  66 + '\n' +
  67 + ' message InnerObject {\n' +
  68 + ' string key1 = 1;\n' +
  69 + ' bool key2 = 2;\n' +
  70 + ' double key3 = 3;\n' +
  71 + ' int32 key4 = 4;\n' +
  72 + ' string key5 = 5;\n' +
  73 + ' }\n' +
  74 + '}\n';
  75 +
  76 + private defaultAttributesSchema =
  77 + 'syntax ="proto3";\n' +
  78 + 'package attributes;\n' +
  79 + '\n' +
  80 + 'message SensorConfiguration {\n' +
  81 + ' string firmwareVersion = 1;\n' +
  82 + ' string serialNumber = 2;\n' +
  83 + '}';
  84 +
57 private requiredValue: boolean; 85 private requiredValue: boolean;
58 86
59 get required(): boolean { 87 get required(): boolean {
@@ -83,17 +111,18 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control @@ -83,17 +111,18 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
83 111
84 ngOnInit() { 112 ngOnInit() {
85 this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({ 113 this.mqttDeviceProfileTransportConfigurationFormGroup = this.fb.group({
86 - configuration: this.fb.group({  
87 deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]], 114 deviceAttributesTopic: [null, [Validators.required, this.validationMQTTTopic()]],
88 deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]], 115 deviceTelemetryTopic: [null, [Validators.required, this.validationMQTTTopic()]],
89 transportPayloadTypeConfiguration: this.fb.group({ 116 transportPayloadTypeConfiguration: this.fb.group({
90 - transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required] 117 + transportPayloadType: [MqttTransportPayloadType.JSON, Validators.required],
  118 + deviceTelemetryProtoSchema: [this.defaultTelemetrySchema, Validators.required],
  119 + deviceAttributesProtoSchema: [this.defaultAttributesSchema, Validators.required]
91 }) 120 })
92 - }, {validator: this.uniqueDeviceTopicValidator})  
93 - });  
94 - this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').valueChanges.subscribe(payloadType => {  
95 - this.updateTransportPayloadBasedControls(payloadType);  
96 - this.mqttDeviceProfileTransportConfigurationFormGroup.updateValueAndValidity(); 121 + }, {validator: this.uniqueDeviceTopicValidator}
  122 + );
  123 + this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType')
  124 + .valueChanges.subscribe(payloadType => {
  125 + this.updateTransportPayloadBasedControls(payloadType, true);
97 }); 126 });
98 this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => { 127 this.mqttDeviceProfileTransportConfigurationFormGroup.valueChanges.subscribe(() => {
99 this.updateModel(); 128 this.updateModel();
@@ -110,58 +139,41 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control @@ -110,58 +139,41 @@ export class MqttDeviceProfileTransportConfigurationComponent implements Control
110 } 139 }
111 140
112 get protoPayloadType(): boolean { 141 get protoPayloadType(): boolean {
113 - let transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration.transportPayloadType').value; 142 + const transportPayloadType = this.mqttDeviceProfileTransportConfigurationFormGroup.get('transportPayloadTypeConfiguration.transportPayloadType').value;
114 return transportPayloadType === MqttTransportPayloadType.PROTOBUF; 143 return transportPayloadType === MqttTransportPayloadType.PROTOBUF;
115 } 144 }
116 145
117 writeValue(value: MqttDeviceProfileTransportConfiguration | null): void { 146 writeValue(value: MqttDeviceProfileTransportConfiguration | null): void {
118 if (isDefinedAndNotNull(value)) { 147 if (isDefinedAndNotNull(value)) {
119 - this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration.transportPayloadType);  
120 - this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue({configuration: value}, {emitEvent: false}); 148 + this.mqttDeviceProfileTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
  149 + this.updateTransportPayloadBasedControls(value.transportPayloadTypeConfiguration?.transportPayloadType);
121 } 150 }
122 } 151 }
123 152
124 private updateModel() { 153 private updateModel() {
125 let configuration: DeviceProfileTransportConfiguration = null; 154 let configuration: DeviceProfileTransportConfiguration = null;
126 if (this.mqttDeviceProfileTransportConfigurationFormGroup.valid) { 155 if (this.mqttDeviceProfileTransportConfigurationFormGroup.valid) {
127 - configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.getRawValue().configuration; 156 + configuration = this.mqttDeviceProfileTransportConfigurationFormGroup.value;
128 configuration.type = DeviceTransportType.MQTT; 157 configuration.type = DeviceTransportType.MQTT;
129 } 158 }
130 this.propagateChange(configuration); 159 this.propagateChange(configuration);
131 } 160 }
132 161
133 - private updateTransportPayloadBasedControls(type: MqttTransportPayloadType) {  
134 - const transportPayloadTypeConfigurationFormGroup = this.mqttDeviceProfileTransportConfigurationFormGroup.get('configuration.transportPayloadTypeConfiguration') as FormGroup;  
135 - if (type === MqttTransportPayloadType.PROTOBUF) {  
136 - const defaultTelemetrySchema = "syntax =\"proto3\";\n" +  
137 - "package telemetry;\n" +  
138 - "\n" +  
139 - "message SensorDataReading {\n" +  
140 - "\n" +  
141 - " double temperature = 1;\n" +  
142 - " double humidity = 2;\n" +  
143 - " InnerObject innerObject = 3;\n" +  
144 - "\n" +  
145 - " message InnerObject {\n" +  
146 - " string key1 = 1;\n" +  
147 - " bool key2 = 2;\n" +  
148 - " double key3 = 3;\n" +  
149 - " int32 key4 = 4;\n" +  
150 - " string key5 = 5;\n" +  
151 - " }\n" +  
152 - "}\n";  
153 - const defaultAttributesSchema = "syntax =\"proto3\";\n" +  
154 - "package attributes;\n" +  
155 - "\n" +  
156 - "message SensorConfiguration {\n" +  
157 - " string firmwareVersion = 1;\n" +  
158 - " string serialNumber = 2;\n" +  
159 - "}";  
160 - transportPayloadTypeConfigurationFormGroup.registerControl('deviceTelemetryProtoSchema', this.fb.control(defaultTelemetrySchema, Validators.required));  
161 - transportPayloadTypeConfigurationFormGroup.registerControl('deviceAttributesProtoSchema', this.fb.control(defaultAttributesSchema, Validators.required)); 162 + private updateTransportPayloadBasedControls(type: MqttTransportPayloadType, forceUpdated = false) {
  163 + const transportPayloadTypeForm = this.mqttDeviceProfileTransportConfigurationFormGroup
  164 + .get('transportPayloadTypeConfiguration') as FormGroup;
  165 + if (forceUpdated) {
  166 + transportPayloadTypeForm.patchValue({
  167 + deviceTelemetryProtoSchema: this.defaultTelemetrySchema,
  168 + deviceAttributesProtoSchema: this.defaultAttributesSchema
  169 + }, {emitEvent: false});
  170 + }
  171 + if (type === MqttTransportPayloadType.PROTOBUF && !this.disabled) {
  172 + transportPayloadTypeForm.get('deviceTelemetryProtoSchema').enable({emitEvent: false});
  173 + transportPayloadTypeForm.get('deviceAttributesProtoSchema').enable({emitEvent: false});
162 } else { 174 } else {
163 - transportPayloadTypeConfigurationFormGroup.removeControl('deviceTelemetryProtoSchema');  
164 - transportPayloadTypeConfigurationFormGroup.removeControl('deviceAttributesProtoSchema'); 175 + transportPayloadTypeForm.get('deviceTelemetryProtoSchema').disable({emitEvent: false});
  176 + transportPayloadTypeForm.get('deviceAttributesProtoSchema').disable({emitEvent: false});
165 } 177 }
166 } 178 }
167 179
@@ -41,9 +41,9 @@ @@ -41,9 +41,9 @@
41 </div> 41 </div>
42 </mat-tab> 42 </mat-tab>
43 <mat-tab *ngIf="entity" 43 <mat-tab *ngIf="entity"
44 - label="{{'device-profile.alarm-rules' | translate:  
45 - {count: entity.profileData.alarms && entity.profileData.alarms.length ?  
46 - entity.profileData.alarms.length : 0} }}" #alarmRules="matTab"> 44 + label="{{'device-profile.alarm-rules-with-count' | translate:
  45 + {count: entity.profileData?.alarms?.length ? entity.profileData.alarms.length : 0}
  46 + }}" #alarmRules="matTab">
47 <div class="mat-padding" [formGroup]="detailsForm"> 47 <div class="mat-padding" [formGroup]="detailsForm">
48 <div formGroupName="profileData"> 48 <div formGroupName="profileData">
49 <tb-device-profile-alarms formControlName="alarms"></tb-device-profile-alarms> 49 <tb-device-profile-alarms formControlName="alarms"></tb-device-profile-alarms>