diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts
index d583369016..5209dd3602 100644
--- a/ui-ngx/src/app/modules/home/components/home-components.module.ts
+++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts
@@ -107,6 +107,7 @@ import { AlarmRuleKeyFiltersDialogComponent } from './profile/alarm/alarm-rule-k
import { FilterTextComponent } from './filter/filter-text.component';
import { AddDeviceProfileDialogComponent } from './profile/add-device-profile-dialog.component';
import { RuleChainAutocompleteComponent } from './rule-chain/rule-chain-autocomplete.component';
+import { DeviceProfileProvisionConfigurationComponent } from "./profile/device-profile-provision-configuration.component";
@NgModule({
declarations:
@@ -196,7 +197,8 @@ import { RuleChainAutocompleteComponent } from './rule-chain/rule-chain-autocomp
DeviceProfileComponent,
DeviceProfileDialogComponent,
AddDeviceProfileDialogComponent,
- RuleChainAutocompleteComponent
+ RuleChainAutocompleteComponent,
+ DeviceProfileProvisionConfigurationComponent
],
imports: [
CommonModule,
@@ -275,7 +277,8 @@ import { RuleChainAutocompleteComponent } from './rule-chain/rule-chain-autocomp
DeviceProfileComponent,
DeviceProfileDialogComponent,
AddDeviceProfileDialogComponent,
- RuleChainAutocompleteComponent
+ RuleChainAutocompleteComponent,
+ DeviceProfileProvisionConfigurationComponent
],
providers: [
WidgetComponentService,
diff --git a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html
index d7f119a3b7..bda26153d1 100644
--- a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html
@@ -93,6 +93,14 @@
+
+
+
@@ -107,7 +115,7 @@
+ (click)="nextStep()">{{ (selectedIndex === 3 ? 'action.add' : 'action.continue') | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts
index 476c69488f..42edc3c613 100644
--- a/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts
+++ b/ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.ts
@@ -77,6 +77,8 @@ export class AddDeviceProfileDialogComponent extends
alarmRulesFormGroup: FormGroup;
+ provisionConfigurationFormGroup: FormGroup;
+
constructor(protected store: Store,
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: AddDeviceProfileDialogData,
@@ -111,6 +113,12 @@ export class AddDeviceProfileDialogComponent extends
alarms: [null]
}
);
+
+ this.provisionConfigurationFormGroup = this.fb.group(
+ {
+ provisionConfiguration: [null]
+ }
+ )
}
private deviceProfileTransportTypeChanged() {
@@ -131,7 +139,7 @@ export class AddDeviceProfileDialogComponent extends
}
nextStep() {
- if (this.selectedIndex < 2) {
+ if (this.selectedIndex < 3) {
this.addDeviceProfileStepper.next();
} else {
this.add();
@@ -146,6 +154,8 @@ export class AddDeviceProfileDialogComponent extends
return this.transportConfigFormGroup;
case 2:
return this.alarmRulesFormGroup;
+ case 3:
+ return this.provisionConfigurationFormGroup;
}
}
@@ -154,11 +164,17 @@ export class AddDeviceProfileDialogComponent extends
name: this.deviceProfileDetailsFormGroup.get('name').value,
type: this.deviceProfileDetailsFormGroup.get('type').value,
transportType: this.transportConfigFormGroup.get('transportType').value,
+ provisionType: this.provisionConfigurationFormGroup.get('provisionConfiguration').value.type,
+ provisionDeviceKey: this.provisionConfigurationFormGroup.get('provisionConfiguration').value.provisionDeviceKey,
description: this.deviceProfileDetailsFormGroup.get('description').value,
profileData: {
configuration: createDeviceProfileConfiguration(DeviceProfileType.DEFAULT),
transportConfiguration: this.transportConfigFormGroup.get('transportConfiguration').value,
- alarms: this.alarmRulesFormGroup.get('alarms').value
+ alarms: this.alarmRulesFormGroup.get('alarms').value,
+ provisionConfiguration: {
+ type: this.provisionConfigurationFormGroup.get('provisionConfiguration').value.type,
+ provisionDeviceSecret: this.provisionConfigurationFormGroup.get('provisionConfiguration').value.provisionDeviceSecret
+ }
}
};
if (this.deviceProfileDetailsFormGroup.get('defaultRuleChainId').value) {
diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.html b/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.html
index daae838285..eb4aef68eb 100644
--- a/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.html
+++ b/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.html
@@ -51,5 +51,15 @@
formControlName="alarms">
+
+
+
+ device-profile.device-provisioning
+
+
+
+
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.ts b/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.ts
index 7d7fc55057..5b7fd9b998 100644
--- a/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.ts
+++ b/ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.ts
@@ -72,7 +72,8 @@ export class DeviceProfileDataComponent implements ControlValueAccessor, OnInit
this.deviceProfileDataFormGroup = this.fb.group({
configuration: [null, Validators.required],
transportConfiguration: [null, Validators.required],
- alarms: [null]
+ alarms: [null],
+ provisionConfiguration: [null]
});
this.deviceProfileDataFormGroup.valueChanges.subscribe(() => {
this.updateModel();
@@ -98,6 +99,7 @@ export class DeviceProfileDataComponent implements ControlValueAccessor, OnInit
this.deviceProfileDataFormGroup.patchValue({configuration: value?.configuration}, {emitEvent: false});
this.deviceProfileDataFormGroup.patchValue({transportConfiguration: value?.transportConfiguration}, {emitEvent: false});
this.deviceProfileDataFormGroup.patchValue({alarms: value?.alarms}, {emitEvent: false});
+ this.deviceProfileDataFormGroup.patchValue({provisionConfiguration: value?.provisionConfiguration}, {emitEvent: false});
}
private updateModel() {
diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.html
new file mode 100644
index 0000000000..46d15905d1
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.html
@@ -0,0 +1,46 @@
+
+
+
+ device-profile.provision-strategy
+
+
+ {{deviceProvisionTypeTranslateMap.get(type) | translate}}
+
+
+
+ {{ 'device-profile.provision-strategy-required' | translate }}
+
+
+
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.ts
new file mode 100644
index 0000000000..f37d8bb2c6
--- /dev/null
+++ b/ui-ngx/src/app/modules/home/components/profile/device-profile-provision-configuration.component.ts
@@ -0,0 +1,140 @@
+///
+/// Copyright © 2016-2020 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 { Component, forwardRef, Input, OnInit } from "@angular/core";
+import {
+ ControlValueAccessor,
+ FormBuilder,
+ FormControl,
+ FormGroup,
+ NG_VALIDATORS,
+ NG_VALUE_ACCESSOR,
+ ValidationErrors,
+ Validator,
+ Validators
+} from "@angular/forms";
+import { coerceBooleanProperty } from "@angular/cdk/coercion";
+import {
+ DeviceProvisionConfiguration,
+ DeviceProvisionType,
+ deviceProvisionTypeTranslationMap
+} from "@shared/models/device.models";
+import { isDefinedAndNotNull } from "@core/utils";
+
+@Component({
+ selector: 'tb-device-profile-provision-configuration',
+ templateUrl: './device-profile-provision-configuration.component.html',
+ styleUrls: [],
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => DeviceProfileProvisionConfigurationComponent),
+ multi: true
+ },
+ {
+ provide: NG_VALIDATORS,
+ useExisting: forwardRef(() => DeviceProfileProvisionConfigurationComponent),
+ multi: true,
+ }
+ ]
+})
+export class DeviceProfileProvisionConfigurationComponent implements ControlValueAccessor, OnInit, Validator {
+
+ provisionConfigurationFormGroup: FormGroup;
+
+ deviceProvisionType = DeviceProvisionType;
+ deviceProvisionTypes = Object.keys(DeviceProvisionType);
+ deviceProvisionTypeTranslateMap = deviceProvisionTypeTranslationMap;
+
+ private requiredValue: boolean;
+ get required(): boolean {
+ return this.requiredValue;
+ }
+ @Input()
+ set required(value: boolean) {
+ this.requiredValue = coerceBooleanProperty(value);
+ }
+
+ @Input()
+ disabled: boolean;
+
+ private propagateChange = (v: any) => { };
+
+ constructor(private fb: FormBuilder) {
+ }
+
+ ngOnInit(): void {
+ this.provisionConfigurationFormGroup = this.fb.group({
+ type: [DeviceProvisionType.DISABLED, Validators.required],
+ provisionDeviceSecret: [{value: null, disabled: true}, Validators.required],
+ provisionDeviceKey: [{value: null, disabled: true}, Validators.required]
+ });
+ this.provisionConfigurationFormGroup.get('type').valueChanges.subscribe((type) => {
+ if(type === DeviceProvisionType.DISABLED) {
+ this.provisionConfigurationFormGroup.get('provisionDeviceSecret').disable({emitEvent: false});
+ this.provisionConfigurationFormGroup.get('provisionDeviceSecret').patchValue(null,{emitEvent: false});
+ this.provisionConfigurationFormGroup.get('provisionDeviceKey').disable({emitEvent: false});
+ this.provisionConfigurationFormGroup.get('provisionDeviceKey').patchValue(null);
+ } else {
+ this.provisionConfigurationFormGroup.get('provisionDeviceSecret').enable({emitEvent: false});
+ this.provisionConfigurationFormGroup.get('provisionDeviceKey').enable({emitEvent: false});
+ }
+ });
+ this.provisionConfigurationFormGroup.valueChanges.subscribe(() => {
+ this.updateModel();
+ });
+ }
+
+ registerOnChange(fn: any): void {
+ this.propagateChange = fn;
+ }
+
+ registerOnTouched(fn: any): void {
+ }
+
+ writeValue(value: DeviceProvisionConfiguration | null): void {
+ if(isDefinedAndNotNull(value)){
+ this.provisionConfigurationFormGroup.patchValue(value, {emitEvent: false});
+ } else {
+ this.provisionConfigurationFormGroup.patchValue({type: DeviceProvisionType.DISABLED});
+ }
+ }
+
+ setDisabledState(isDisabled: boolean){
+ this.disabled = isDisabled;
+ if(this.disabled){
+ this.provisionConfigurationFormGroup.disable();
+ } else {
+ this.provisionConfigurationFormGroup.enable({emitEvent: false});
+ }
+ }
+
+ validate(c: FormControl): ValidationErrors | null {
+ return (this.provisionConfigurationFormGroup.valid) ? null : {
+ provisionConfiguration: {
+ valid: false,
+ },
+ };
+ }
+
+ private updateModel(): void {
+ let deviceProvisionConfiguration: DeviceProvisionConfiguration = null;
+ if (this.provisionConfigurationFormGroup.valid) {
+ deviceProvisionConfiguration = this.provisionConfigurationFormGroup.getRawValue();
+ }
+ this.propagateChange(deviceProvisionConfiguration);
+ }
+}
diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts
index e3c441c8a2..9c5fc9b5a5 100644
--- a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts
+++ b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts
@@ -126,6 +126,10 @@ export class DeviceProfileComponent extends EntityComponent {
}
updateForm(entity: DeviceProfile) {
+ if(entity?.profileData?.provisionConfiguration) {
+ entity.profileData.provisionConfiguration.provisionDeviceKey = entity?.provisionDeviceKey;
+ }
+
this.entityForm.patchValue({name: entity.name});
this.entityForm.patchValue({type: entity.type}, {emitEvent: false});
this.entityForm.patchValue({transportType: entity.transportType}, {emitEvent: false});
@@ -138,7 +142,11 @@ export class DeviceProfileComponent extends EntityComponent {
if (formValue.defaultRuleChainId) {
formValue.defaultRuleChainId = new RuleChainId(formValue.defaultRuleChainId);
}
- return formValue;
+ formValue.provisionType = formValue.profileData.provisionConfiguration.type;
+ formValue.provisionDeviceKey = formValue.profileData.provisionConfiguration.provisionDeviceKey;
+ delete formValue.profileData.provisionConfiguration.provisionDeviceKey;
+
+ return super.prepareFormValue(formValue);
}
onDeviceProfileIdCopied(event) {
diff --git a/ui-ngx/src/app/shared/models/device.models.ts b/ui-ngx/src/app/shared/models/device.models.ts
index fe92268b80..a0d91c908e 100644
--- a/ui-ngx/src/app/shared/models/device.models.ts
+++ b/ui-ngx/src/app/shared/models/device.models.ts
@@ -36,6 +36,12 @@ export enum DeviceTransportType {
LWM2M = 'LWM2M'
}
+export enum DeviceProvisionType {
+ DISABLED = 'DISABLED',
+ ALLOW_CREATE_NEW_DEVICES = 'ALLOW_CREATE_NEW_DEVICES',
+ CHECK_PRE_PROVISIONED_DEVICES = 'CHECK_PRE_PROVISIONED_DEVICES'
+}
+
export interface DeviceConfigurationFormInfo {
hasProfileConfiguration: boolean;
hasDeviceConfiguration: boolean;
@@ -67,6 +73,15 @@ export const deviceTransportTypeTranslationMap = new Map(
+ [
+ [DeviceProvisionType.DISABLED, 'device-profile.provision-strategy-disabled'],
+ [DeviceProvisionType.ALLOW_CREATE_NEW_DEVICES, 'device-profile.provision-strategy-created-new'],
+ [DeviceProvisionType.CHECK_PRE_PROVISIONED_DEVICES, 'device-profile.provision-strategy-check-pre-provisioned']
+ ]
+)
+
export const deviceTransportTypeConfigurationInfoMap = new Map(
[
[
@@ -125,6 +140,12 @@ export interface DeviceProfileTransportConfiguration extends DeviceProfileTransp
type: DeviceTransportType;
}
+export interface DeviceProvisionConfiguration {
+ type: DeviceProvisionType;
+ provisionDeviceSecret?: string;
+ provisionDeviceKey?: string;
+}
+
export function createDeviceProfileConfiguration(type: DeviceProfileType): DeviceProfileConfiguration {
let configuration: DeviceProfileConfiguration = null;
if (type) {
@@ -220,6 +241,7 @@ export interface DeviceProfileData {
configuration: DeviceProfileConfiguration;
transportConfiguration: DeviceProfileTransportConfiguration;
alarms?: Array;
+ provisionConfiguration?: DeviceProvisionConfiguration;
}
export interface DeviceProfile extends BaseData {
@@ -229,6 +251,8 @@ export interface DeviceProfile extends BaseData {
default?: boolean;
type: DeviceProfileType;
transportType: DeviceTransportType;
+ provisionType: DeviceProvisionType;
+ provisionDeviceKey?: string;
defaultRuleChainId?: RuleChainId;
profileData: DeviceProfileData;
}
diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json
index c98a2d5c17..23d2fba8df 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -840,7 +840,17 @@
"alarm-details": "Alarm details",
"alarm-rule-condition": "Alarm rule condition",
"enter-alarm-rule-condition-prompt": "Please add alarm rule condition",
- "edit-alarm-rule-condition": "Edit alarm rule condition"
+ "edit-alarm-rule-condition": "Edit alarm rule condition",
+ "device-provisioning": "Device provisioning",
+ "provision-strategy": "Provision strategy",
+ "provision-strategy-required": "Provision strategy is required.",
+ "provision-strategy-disabled": "Disabled",
+ "provision-strategy-created-new": "Allow create new devices",
+ "provision-strategy-check-pre-provisioned": "Check pre provisioned devices",
+ "provision-device-key": "Provision device key",
+ "provision-device-key-required": "Provision device key is required.",
+ "provision-device-secret": "Provision device secret",
+ "provision-device-secret-required": "Provision device secret is required."
},
"dialog": {
"close": "Close dialog"