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 23fdf04cde..42ef973988 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 @@ -100,6 +100,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html index c8433fde7c..df0d5af5a3 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html @@ -34,9 +34,7 @@
diff --git a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html index 917ad25dd2..d96d1788c7 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device-profile.component.html @@ -138,6 +138,7 @@ 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 5621e60418..6492cc2d1e 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 @@ -67,6 +67,8 @@ export class DeviceProfileComponent extends EntityComponent { displayTransportConfiguration: boolean; + isTransportTypeChanged = false; + serviceType = ServiceType.TB_RULE_ENGINE; deviceProfileId: EntityId; @@ -158,6 +160,7 @@ export class DeviceProfileComponent extends EntityComponent { const deviceTransportType: DeviceTransportType = form.get('transportType').value; this.displayTransportConfiguration = deviceTransportType && deviceTransportTypeConfigurationInfoMap.get(deviceTransportType).hasProfileConfiguration; + this.isTransportTypeChanged = true; let profileData: DeviceProfileData = form.getRawValue().profileData; if (!profileData) { profileData = { diff --git a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html index f8fb2c7baa..87c222216c 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html @@ -37,6 +37,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts index 7d74cbc387..c889fc7eb8 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts @@ -50,6 +50,9 @@ export class DeviceProfileTransportConfigurationComponent implements ControlValu @Input() disabled: boolean; + @Input() + isAdd: boolean; + transportType: DeviceTransportType; private propagateChange = (v: any) => { }; diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.html new file mode 100644 index 0000000000..34441d55f5 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.html @@ -0,0 +1,55 @@ + +
+ +

device-profile.lwm2m.add-new-server-title

+ + +
+ + +
+
+ + {{ 'device-profile.lwm2m.server-type' | translate }} + + + {{ serverConfigTypeNamesMap.get(serverType) | translate }} + + + +
+
+ + + +
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts new file mode 100644 index 0000000000..55fcc7d751 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts @@ -0,0 +1,60 @@ +/// +/// Copyright © 2016-2021 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 } from '@angular/core'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { Router } from '@angular/router'; +import { MatDialogRef } from '@angular/material/dialog'; +import { + ServerConfigType, + ServerConfigTypeTranslationMap +} from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; + +@Component({ + selector: 'tb-profile-lwm2m-bootstrap-add-config-server-dialog', + templateUrl: './lwm2m-bootstrap-add-config-server-dialog.component.html' +}) +export class Lwm2mBootstrapAddConfigServerDialogComponent extends DialogComponent { + + addConfigServerFormGroup: FormGroup; + + serverTypes = Object.values(ServerConfigType); + serverConfigTypeNamesMap = ServerConfigTypeTranslationMap; + + constructor(protected store: Store, + protected router: Router, + private fb: FormBuilder, + public dialogRef: MatDialogRef, + ) { + super(store, router, dialogRef); + this.addConfigServerFormGroup = this.fb.group({ + serverType: [ServerConfigType.LWM2M] + }); + } + + addServerConfig() { + this.dialogRef.close(this.addConfigServerFormGroup.get('serverType').value === ServerConfigType.BOOTSTRAP); + } + + cancel(): void { + this.dialogRef.close(null); + } +} + + diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html new file mode 100644 index 0000000000..cd00d1661a --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html @@ -0,0 +1,39 @@ + +
+ +
+ + +
+
+
+ device-profile.lwm2m.no-config-servers +
+
+ +
+
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts new file mode 100644 index 0000000000..a4bf5d4958 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts @@ -0,0 +1,185 @@ +/// +/// Copyright © 2016-2021 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 { + AbstractControl, + ControlValueAccessor, + FormArray, + FormBuilder, FormControl, + FormGroup, + NG_VALIDATORS, + NG_VALUE_ACCESSOR +} from '@angular/forms'; +import { of, Subscription } from 'rxjs'; +import { ServerSecurityConfig } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; +import { TranslateService } from '@ngx-translate/core'; +import { DialogService } from '@core/services/dialog.service'; +import { MatDialog } from '@angular/material/dialog'; +import { Lwm2mBootstrapAddConfigServerDialogComponent } from '@home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component'; +import { mergeMap } from 'rxjs/operators'; +import { DeviceProfileService } from '@core/http/device-profile.service'; +import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models'; + +@Component({ + selector: 'tb-profile-lwm2m-bootstrap-config-servers', + templateUrl: './lwm2m-bootstrap-config-servers.component.html', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), + multi: true + }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => Lwm2mBootstrapConfigServersComponent), + multi: true, + } + ] +}) +export class Lwm2mBootstrapConfigServersComponent implements OnInit, ControlValueAccessor { + + bootstrapConfigServersFormGroup: FormGroup; + + @Input() + disabled: boolean; + + private valueChangeSubscription: Subscription = null; + + private propagateChange = (v: any) => { }; + + constructor(public translate: TranslateService, + public matDialog: MatDialog, + private dialogService: DialogService, + private deviceProfileService: DeviceProfileService, + private fb: FormBuilder) { + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + ngOnInit() { + this.bootstrapConfigServersFormGroup = this.fb.group({ + serverConfigs: this.fb.array([]) + }); + } + + serverConfigsFromArray(): FormArray { + return this.bootstrapConfigServersFormGroup.get('serverConfigs') as FormArray; + } + + setDisabledState(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.bootstrapConfigServersFormGroup.disable({emitEvent: false}); + } else { + this.bootstrapConfigServersFormGroup.enable({emitEvent: false}); + } + } + + writeValue(serverConfigs: Array | null): void { + if (this.valueChangeSubscription) { + this.valueChangeSubscription.unsubscribe(); + } + const serverConfigsControls: Array = []; + if (serverConfigs) { + serverConfigs.forEach((serverConfig) => { + serverConfigsControls.push(this.fb.control(serverConfig)); + }); + } + this.bootstrapConfigServersFormGroup.setControl('serverConfigs', this.fb.array(serverConfigsControls)); + if (this.disabled) { + this.bootstrapConfigServersFormGroup.disable({emitEvent: false}); + } else { + this.bootstrapConfigServersFormGroup.enable({emitEvent: false}); + } + this.valueChangeSubscription = this.bootstrapConfigServersFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + } + + trackByParams(index: number): number { + return index; + } + + removeServerConfig($event: Event, index: number) { + if ($event) { + $event.stopPropagation(); + $event.preventDefault(); + } + this.dialogService.confirm( + this.translate.instant('device-profile.lwm2m.delete-server-title'), + this.translate.instant('device-profile.lwm2m.delete-server-text'), + this.translate.instant('action.no'), + this.translate.instant('action.yes'), + true + ).subscribe((result) => { + if (result) { + this.serverConfigsFromArray().removeAt(index); + } + }); + } + + addServerConfig(): void { + const addDialogObs = this.isBootstrapAdded() ? of(false) : + this.matDialog.open(Lwm2mBootstrapAddConfigServerDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'] + }).afterClosed(); + const addServerConfigObs = addDialogObs.pipe( + mergeMap((isBootstrap) => { + if (isBootstrap === null) { + return of(null); + } + return this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(isBootstrap, Lwm2mSecurityType.NO_SEC); + }) + ); + addServerConfigObs.subscribe((serverConfig) => { + if (serverConfig) { + serverConfig.securityMode = Lwm2mSecurityType.NO_SEC; + this.serverConfigsFromArray().push(this.fb.control(serverConfig)); + this.updateModel(); + } + }); + } + + public validate(c: FormControl) { + return (this.bootstrapConfigServersFormGroup.valid) ? null : { + serverConfigs: { + valid: false, + }, + }; + } + + public isBootstrapAdded() { + const serverConfigsArray = this.serverConfigsFromArray().getRawValue(); + for (let i = 0; i < serverConfigsArray.length; i++) { + if (serverConfigsArray[i].bootstrapServerIs) { + return true; + } + } + return false; + } + + private updateModel() { + const serverConfigs: Array = this.serverConfigsFromArray().value; + this.propagateChange(serverConfigs); + } +} diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html index 3fe4e7cda8..4019c7bf65 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html @@ -15,99 +15,170 @@ limitations under the License. --> -
-
- - {{ 'device-profile.lwm2m.mode' | translate }} - - - {{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityMode]) }} - - - - - {{ 'device-profile.lwm2m.server-host' | translate }} - - - {{ 'device-profile.lwm2m.server-host-required' | translate }} - - - - {{ 'device-profile.lwm2m.server-port' | translate }} - - - {{ 'device-profile.lwm2m.server-port-required' | translate }} - - - {{ 'device-profile.lwm2m.server-port-pattern' | translate }} - - + +
+ +
+
{{ (serverFormGroup.get('bootstrapServerIs').value ? + 'device-profile.lwm2m.bootstrap-server' : 'device-profile.lwm2m.lwm2m-server') | translate }}
+
+
{{ ('device-profile.lwm2m.short-id' | translate) + ': ' }} + {{ serverFormGroup.get('shortServerId').value }} +
+
{{ ('device-profile.lwm2m.mode' | translate) + ': ' }} + {{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[serverFormGroup.get('securityMode').value]) }} +
+
+
+
+ + +
+
+ +
+
+ + {{ 'device-profile.lwm2m.mode' | translate }} + + + {{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityMode]) }} + + + + + {{ 'device-profile.lwm2m.short-id' | translate }} + help + + + {{ 'device-profile.lwm2m.short-id-required' | translate }} + + + {{ 'device-profile.lwm2m.short-id-pattern' | translate }} + + + {{ 'device-profile.lwm2m.short-id-range' | translate }} + + +
+
+ + {{ 'device-profile.lwm2m.server-host' | translate }} + + + {{ 'device-profile.lwm2m.server-host-required' | translate }} + + + + {{ 'device-profile.lwm2m.server-port' | translate }} + + + {{ 'device-profile.lwm2m.server-port-required' | translate }} + + + {{ 'device-profile.lwm2m.server-port-pattern' | translate }} + + - {{ 'device-profile.lwm2m.server-port-range' | translate }} - - -
-
- - {{ 'device-profile.lwm2m.short-id' | translate }} - help - - - {{ 'device-profile.lwm2m.short-id-required' | translate }} - - - {{ 'device-profile.lwm2m.short-id-pattern' | translate }} - - - {{ 'device-profile.lwm2m.short-id-range' | translate }} - - - - {{ 'device-profile.lwm2m.client-hold-off-time' | translate }} - help - - - {{ 'device-profile.lwm2m.client-hold-off-time-required' | translate }} - - + + {{ 'device-profile.lwm2m.client-hold-off-time' | translate }} + help + + + {{ 'device-profile.lwm2m.client-hold-off-time-required' | translate }} + + - {{ 'device-profile.lwm2m.client-hold-off-time-pattern' | translate }} - - - - {{ 'device-profile.lwm2m.account-after-timeout' | translate }} - help - - - {{ 'device-profile.lwm2m.account-after-timeout-required' | translate }} - - help + + + {{ 'device-profile.lwm2m.account-after-timeout-required' | translate }} + + - {{ 'device-profile.lwm2m.account-after-timeout-pattern' | translate }} - - -
-
- - {{ 'device-profile.lwm2m.server-public-key' | translate }} - help - - - {{ 'device-profile.lwm2m.server-public-key-required' | translate }} - - -
-
+ {{ 'device-profile.lwm2m.account-after-timeout-pattern' | translate }} +
+
+
+
+ + {{ 'device-profile.lwm2m.server-public-key' | translate }} + help + + + {{ 'device-profile.lwm2m.server-public-key-required' | translate }} + + +
+
+ + {{ 'device-profile.lwm2m.lifetime' | translate }} + + + {{ 'device-profile.lwm2m.lifetime-required' | translate }} + + + {{ 'device-profile.lwm2m.lifetime-pattern' | translate }} + + + + {{ 'device-profile.lwm2m.default-min-period' | translate }} + help + + + {{ 'device-profile.lwm2m.default-min-period-required' | translate }} + + + {{ 'device-profile.lwm2m.default-min-period-pattern' | translate }} + + +
+ + {{ 'device-profile.lwm2m.binding' | translate }} + help + + + {{ bindingModeTypeNamesMap.get(bindingMode) | translate }} + + + + + {{ 'device-profile.lwm2m.notification-storing' | translate }} + +
+
+ diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts index 9492b18114..c92cf9ef45 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, EventEmitter, forwardRef, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { ControlValueAccessor, FormBuilder, @@ -26,8 +26,7 @@ import { Validators } from '@angular/forms'; import { - DEFAULT_PORT_BOOTSTRAP_NO_SEC, - DEFAULT_PORT_SERVER_NO_SEC, + BingingMode, BingingModeTranslationsMap, ServerSecurityConfig } from './lwm2m-profile-config.models'; import { DeviceProfileService } from '@core/http/device-profile.service'; @@ -65,14 +64,16 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc private isDataLoadedIntoCache = false; serverFormGroup: FormGroup; + bindingModeTypes = Object.values(BingingMode); + bindingModeTypeNamesMap = BingingModeTranslationsMap; securityConfigLwM2MType = Lwm2mSecurityType; securityConfigLwM2MTypes = Object.keys(Lwm2mSecurityType); credentialTypeLwM2MNamesMap = Lwm2mSecurityTypeTranslationMap; publicKeyOrIdTooltipNamesMap = Lwm2mPublicKeyOrIdTooltipTranslationsMap; currentSecurityMode = null; - @Input() - isBootstrapServer = false; + @Output() + removeServer = new EventEmitter(); private propagateChange = (v: any) => { }; @@ -83,19 +84,29 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc ngOnInit(): void { this.serverFormGroup = this.fb.group({ host: ['', Validators.required], - port: [this.isBootstrapServer ? DEFAULT_PORT_BOOTSTRAP_NO_SEC : DEFAULT_PORT_SERVER_NO_SEC, - [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]], + port: ['', [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]], securityMode: [Lwm2mSecurityType.NO_SEC], serverPublicKey: [''], clientHoldOffTime: ['', [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], - serverId: ['', [Validators.required, Validators.min(1), Validators.max(65534), Validators.pattern('[0-9]*')]], + shortServerId: ['', [Validators.required, Validators.min(1), Validators.max(65534), Validators.pattern('[0-9]*')]], bootstrapServerAccountTimeout: ['', [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], + binding: [''], + lifetime: [null, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], + notifIfDisabled: [], + defaultMinPeriod: [null, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], + bootstrapServerIs: [] }); this.serverFormGroup.get('securityMode').valueChanges.pipe( - tap(securityMode => this.updateValidate(securityMode)), + tap((securityMode) => { + this.currentSecurityMode = securityMode; + this.updateValidate(securityMode); + }), mergeMap(securityMode => this.getLwm2mBootstrapSecurityInfo(securityMode)), takeUntil(this.destroy$) ).subscribe(serverSecurityConfig => { + if (this.currentSecurityMode !== Lwm2mSecurityType.NO_SEC) { + this.changeSecurityHostPortFields(serverSecurityConfig); + } this.serverFormGroup.patchValue(serverSecurityConfig, {emitEvent: false}); }); this.serverFormGroup.valueChanges.pipe( @@ -114,8 +125,13 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc if (serverData) { this.serverFormGroup.patchValue(serverData, {emitEvent: false}); this.updateValidate(serverData.securityMode); + if (serverData.securityHost && serverData.securityPort) { + delete serverData.securityHost; + delete serverData.securityPort; + this.propagateChangeState(this.serverFormGroup.getRawValue()); + } } - if (!this.isDataLoadedIntoCache){ + if (!this.isDataLoadedIntoCache) { this.getLwm2mBootstrapSecurityInfo().subscribe(value => { if (!serverData) { this.serverFormGroup.patchValue(value); @@ -171,11 +187,17 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc } private getLwm2mBootstrapSecurityInfo(securityMode = Lwm2mSecurityType.NO_SEC): Observable { - return this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(this.isBootstrapServer, securityMode).pipe( + return this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType( + this.serverFormGroup.get('bootstrapServerIs').value, securityMode).pipe( tap(() => this.isDataLoadedIntoCache = true) ); } + private changeSecurityHostPortFields(serverData: ServerSecurityConfig): void { + serverData.port = serverData.securityPort; + serverData.host = serverData.securityHost; + } + validate(): ValidationErrors | null { return this.serverFormGroup.valid ? null : { serverFormGroup: true diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html index a042ba5ea3..20cbd63168 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html @@ -33,93 +33,9 @@
-
- - - - {{ 'device-profile.lwm2m.server' | translate }} - - -
- - {{ 'device-profile.lwm2m.short-id' | translate }} - help - - - {{ 'device-profile.lwm2m.short-id-required' | translate }} - - - {{ 'device-profile.lwm2m.short-id-range' | translate }} - - - {{ 'device-profile.lwm2m.short-id-pattern' | translate }} - - - - {{ 'device-profile.lwm2m.lifetime' | translate }} - - - {{ 'device-profile.lwm2m.lifetime-required' | translate }} - - - {{ 'device-profile.lwm2m.lifetime-pattern' | translate }} - - - - {{ 'device-profile.lwm2m.default-min-period' | translate }} - help - - - {{ 'device-profile.lwm2m.default-min-period-required' | translate }} - - - {{ 'device-profile.lwm2m.default-min-period-pattern' | translate }} - - -
- - {{ 'device-profile.lwm2m.binding' | translate }} - help - - - {{ bindingModeTypeNamesMap.get(bindingMode) | translate }} - - - - - {{ 'device-profile.lwm2m.notification-storing' | translate }} - -
-
- - - {{ 'device-profile.lwm2m.bootstrap-server' | translate }} - - - - - - - - - {{ 'device-profile.lwm2m.lwm2m-server' | translate }} - - - - - - -
+
+ +
diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts index 792aa3c315..1fdf6cf8be 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts @@ -28,20 +28,11 @@ import { import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { ATTRIBUTE, - BingingMode, - BingingModeTranslationsMap, - DEFAULT_BINDING, DEFAULT_EDRX_CYCLE, DEFAULT_FW_UPDATE_RESOURCE, - DEFAULT_ID_SERVER, - DEFAULT_LIFE_TIME, - DEFAULT_MIN_PERIOD, - DEFAULT_NOTIF_IF_DESIBLED, DEFAULT_PAGING_TRANSMISSION_WINDOW, DEFAULT_PSM_ACTIVITY_TIMER, DEFAULT_SW_UPDATE_RESOURCE, - getDefaultBootstrapServerSecurityConfig, - getDefaultLwM2MServerSecurityConfig, Instance, INSTANCES, KEY_NAME, @@ -60,6 +51,7 @@ import { Direction } from '@shared/models/page/sort-order'; import _ from 'lodash'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models'; @Component({ selector: 'tb-profile-lwm2m-device-transport-configuration', @@ -83,8 +75,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro private requiredValue: boolean; private destroy$ = new Subject(); - bindingModeTypes = Object.values(BingingMode); - bindingModeTypeNamesMap = BingingModeTranslationsMap; lwm2mDeviceProfileFormGroup: FormGroup; configurationValue: Lwm2mProfileConfigModels; sortFunction: (key: string, value: object) => object; @@ -98,6 +88,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro this.requiredValue = coerceBooleanProperty(value); } + @Input() + isAdd: boolean; + private propagateChange = (v: any) => { } @@ -106,17 +99,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro this.lwm2mDeviceProfileFormGroup = this.fb.group({ objectIds: [null], observeAttrTelemetry: [null], - bootstrap: this.fb.group({ - servers: this.fb.group({ - binding: [DEFAULT_BINDING], - shortId: [DEFAULT_ID_SERVER, [Validators.required, Validators.min(1), Validators.max(65534), Validators.pattern('[0-9]*')]], - lifetime: [DEFAULT_LIFE_TIME, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], - notifIfDisabled: [DEFAULT_NOTIF_IF_DESIBLED, []], - defaultMinPeriod: [DEFAULT_MIN_PERIOD, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], - }), - bootstrapServer: [null, Validators.required], - lwm2mServer: [null, Validators.required] - }), + bootstrap: [[]], clientLwM2mSettings: this.fb.group({ clientOnlyObserveAfterConnect: [1, []], fwUpdateStrategy: [1, []], @@ -187,9 +170,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro async writeValue(value: Lwm2mProfileConfigModels | null) { if (isDefinedAndNotNull(value) && (value?.clientLwM2mSettings || value?.observeAttr || value?.bootstrap)) { this.configurationValue = value; - const defaultFormSettings = value.clientLwM2mSettings.fwUpdateStrategy === 1 && - isUndefined(value.clientLwM2mSettings.fwUpdateResource); - if (defaultFormSettings) { + if (this.isAdd) { await this.defaultProfileConfig(); } this.initWriteValue(); @@ -203,23 +184,14 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro } private async defaultProfileConfig(): Promise { - let bootstrap: ServerSecurityConfig; - let lwm2m: ServerSecurityConfig; - try { - [bootstrap, lwm2m] = await Promise.all([ - this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(true).toPromise(), - this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(false).toPromise() - ]); - } catch (e) { - bootstrap = getDefaultBootstrapServerSecurityConfig(); - lwm2m = getDefaultLwM2MServerSecurityConfig(); + const lwm2m: ServerSecurityConfig = await this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(false).toPromise(); + if (lwm2m) { + lwm2m.securityMode = Lwm2mSecurityType.NO_SEC; } - - this.configurationValue.bootstrap.bootstrapServer = bootstrap; - this.configurationValue.bootstrap.lwm2mServer = lwm2m; + this.configurationValue.bootstrap = [lwm2m]; this.lwm2mDeviceProfileFormGroup.patchValue({ bootstrap: this.configurationValue.bootstrap - }, {emitEvent: false}); + }, {emitEvent: true}); } private initWriteValue = (): void => { @@ -282,12 +254,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro } private updateDeviceProfileValue(config): void { - if (this.lwm2mDeviceProfileFormGroup.valid) { + if (this.lwm2mDeviceProfileFormGroup.valid && config.observeAttrTelemetry) { this.updateObserveAttrTelemetryFromGroupToJson(config.observeAttrTelemetry); } - this.configurationValue.bootstrap.bootstrapServer = config.bootstrap.bootstrapServer; - this.configurationValue.bootstrap.lwm2mServer = config.bootstrap.lwm2mServer; - this.configurationValue.bootstrap.servers = config.bootstrap.servers; + this.configurationValue.bootstrap = config.bootstrap; this.configurationValue.clientLwM2mSettings = config.clientLwM2mSettings; this.updateModel(); } diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-components.module.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-components.module.ts index aa801f84dc..77ef7ee81e 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-components.module.ts @@ -22,7 +22,9 @@ import { Lwm2mObserveAttrTelemetryResourcesComponent } from './lwm2m-observe-att import { Lwm2mAttributesDialogComponent } from './lwm2m-attributes-dialog.component'; import { Lwm2mAttributesComponent } from './lwm2m-attributes.component'; import { Lwm2mAttributesKeyListComponent } from './lwm2m-attributes-key-list.component'; +import { Lwm2mBootstrapConfigServersComponent } from '@home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component'; import { Lwm2mDeviceConfigServerComponent } from './lwm2m-device-config-server.component'; +import { Lwm2mBootstrapAddConfigServerDialogComponent } from '@home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component'; import { Lwm2mObjectAddInstancesDialogComponent } from './lwm2m-object-add-instances-dialog.component'; import { Lwm2mObjectAddInstancesListComponent } from './lwm2m-object-add-instances-list.component'; import { CommonModule } from '@angular/common'; @@ -40,7 +42,9 @@ import { DeviceProfileCommonModule } from '@home/components/profile/device/commo Lwm2mAttributesDialogComponent, Lwm2mAttributesComponent, Lwm2mAttributesKeyListComponent, + Lwm2mBootstrapConfigServersComponent, Lwm2mDeviceConfigServerComponent, + Lwm2mBootstrapAddConfigServerDialogComponent, Lwm2mObjectAddInstancesDialogComponent, Lwm2mObjectAddInstancesListComponent, Lwm2mObserveAttrTelemetryInstancesComponent @@ -58,7 +62,9 @@ import { DeviceProfileCommonModule } from '@home/components/profile/device/commo Lwm2mAttributesDialogComponent, Lwm2mAttributesComponent, Lwm2mAttributesKeyListComponent, + Lwm2mBootstrapConfigServersComponent, Lwm2mDeviceConfigServerComponent, + Lwm2mBootstrapAddConfigServerDialogComponent, Lwm2mObjectAddInstancesDialogComponent, Lwm2mObjectAddInstancesListComponent, Lwm2mObserveAttrTelemetryInstancesComponent diff --git a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts index e95d1d22d2..543c000e12 100644 --- a/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts +++ b/ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts @@ -96,6 +96,18 @@ export const AttributeNameTranslationMap = new Map( ] ); +export enum ServerConfigType { + LWM2M = 'LWM2M', + BOOTSTRAP = 'BOOTSTRAP' +} + +export const ServerConfigTypeTranslationMap = new Map( + [ + [ServerConfigType.LWM2M, 'device-profile.lwm2m.lwm2m-server'], + [ServerConfigType.BOOTSTRAP, 'device-profile.lwm2m.bootstrap-server'] + ] +); + export enum PowerMode { PSM = 'PSM', DRX = 'DRX', @@ -110,22 +122,21 @@ export const PowerModeTranslationMap = new Map( ] ); -export interface BootstrapServersSecurityConfig { - shortId: number; - lifetime: number; - defaultMinPeriod: number; - notifIfDisabled: boolean; - binding: string; -} - export interface ServerSecurityConfig { host?: string; port?: number; securityMode: Lwm2mSecurityType; + securityHost?: string; + securityPort?: number; serverPublicKey?: string; clientHoldOffTime?: number; - serverId?: number; + shortServerId?: number; bootstrapServerAccountTimeout: number; + lifetime: number; + defaultMinPeriod: number; + notifIfDisabled: boolean; + binding: string; + bootstrapServerIs: boolean; } export interface ServerSecurityConfigInfo extends ServerSecurityConfig { @@ -134,16 +145,10 @@ export interface ServerSecurityConfigInfo extends ServerSecurityConfig { bootstrapServerIs: boolean; } -interface BootstrapSecurityConfig { - servers: BootstrapServersSecurityConfig; - bootstrapServer: ServerSecurityConfig; - lwm2mServer: ServerSecurityConfig; -} - export interface Lwm2mProfileConfigModels { clientLwM2mSettings: ClientLwM2mSettings; observeAttr: ObservableAttributes; - bootstrap: BootstrapSecurityConfig; + bootstrap: Array; } export interface ClientLwM2mSettings { @@ -167,35 +172,6 @@ export interface ObservableAttributes { attributeLwm2m: AttributesNameValueMap; } -export function getDefaultBootstrapServersSecurityConfig(): BootstrapServersSecurityConfig { - return { - shortId: DEFAULT_ID_SERVER, - lifetime: DEFAULT_LIFE_TIME, - defaultMinPeriod: DEFAULT_MIN_PERIOD, - notifIfDisabled: DEFAULT_NOTIF_IF_DESIBLED, - binding: DEFAULT_BINDING - }; -} - -export function getDefaultBootstrapServerSecurityConfig(): ServerSecurityConfig { - return { - bootstrapServerAccountTimeout: DEFAULT_BOOTSTRAP_SERVER_ACCOUNT_TIME_OUT, - clientHoldOffTime: DEFAULT_CLIENT_HOLD_OFF_TIME, - host: DEFAULT_LOCAL_HOST_NAME, - port: DEFAULT_PORT_BOOTSTRAP_NO_SEC, - securityMode: Lwm2mSecurityType.NO_SEC, - serverId: DEFAULT_ID_BOOTSTRAP, - serverPublicKey: '' - }; -} - -export function getDefaultLwM2MServerSecurityConfig(): ServerSecurityConfig { - const DefaultLwM2MServerSecurityConfig = getDefaultBootstrapServerSecurityConfig(); - DefaultLwM2MServerSecurityConfig.port = DEFAULT_PORT_SERVER_NO_SEC; - DefaultLwM2MServerSecurityConfig.serverId = DEFAULT_ID_SERVER; - return DefaultLwM2MServerSecurityConfig; -} - export function getDefaultProfileObserveAttrConfig(): ObservableAttributes { return { observe: [], diff --git a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html index ae0be158d5..6a84e626d9 100644 --- a/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html @@ -133,6 +133,7 @@ diff --git a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html index f1a7af1e46..a0ce99f3db 100644 --- a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html +++ b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html @@ -35,6 +35,7 @@
diff --git a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts index 2c53f04986..f1afa2559a 100644 --- a/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts +++ b/ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts @@ -38,12 +38,17 @@ export class DeviceProfileTabsComponent extends EntityTabsComponent) { super(store); } ngOnInit() { super.ngOnInit(); + this.detailsForm.get('transportType').valueChanges.subscribe(() => { + this.isTransportTypeChanged = true; + }); } } diff --git a/ui-ngx/src/app/shared/models/device.models.ts b/ui-ngx/src/app/shared/models/device.models.ts index 7ebf7bde47..7fc3d70f78 100644 --- a/ui-ngx/src/app/shared/models/device.models.ts +++ b/ui-ngx/src/app/shared/models/device.models.ts @@ -31,9 +31,6 @@ import { OtaPackageId } from '@shared/models/id/ota-package-id'; import { DashboardId } from '@shared/models/id/dashboard-id'; import { DataType } from '@shared/models/constants'; import { - getDefaultBootstrapServerSecurityConfig, - getDefaultBootstrapServersSecurityConfig, - getDefaultLwM2MServerSecurityConfig, getDefaultProfileClientLwM2mSettingsConfig, getDefaultProfileObserveAttrConfig, PowerMode @@ -384,11 +381,7 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT case DeviceTransportType.LWM2M: const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = { observeAttr: getDefaultProfileObserveAttrConfig(), - bootstrap: { - servers: getDefaultBootstrapServersSecurityConfig(), - bootstrapServer: getDefaultBootstrapServerSecurityConfig(), - lwm2mServer: getDefaultLwM2MServerSecurityConfig() - }, + bootstrap: [], clientLwM2mSettings: getDefaultProfileClientLwM2mSettingsConfig() }; transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; diff --git a/ui-ngx/src/app/shared/models/lwm2m-security-config.models.ts b/ui-ngx/src/app/shared/models/lwm2m-security-config.models.ts index 024433b0c7..3187f0661c 100644 --- a/ui-ngx/src/app/shared/models/lwm2m-security-config.models.ts +++ b/ui-ngx/src/app/shared/models/lwm2m-security-config.models.ts @@ -67,14 +67,9 @@ export interface ServerSecurityConfig { clientSecretKey?: string; } -interface BootstrapSecurityConfig { - bootstrapServer: ServerSecurityConfig; - lwm2mServer: ServerSecurityConfig; -} - export interface Lwm2mSecurityConfigModels { client: ClientSecurityConfig; - bootstrap: BootstrapSecurityConfig; + bootstrap: Array; } @@ -84,10 +79,9 @@ export function getLwm2mSecurityConfigModelsDefault(): Lwm2mSecurityConfigModels securityConfigClientMode: Lwm2mSecurityType.NO_SEC, endpoint: '' }, - bootstrap: { - bootstrapServer: getDefaultServerSecurityConfig(), - lwm2mServer: getDefaultServerSecurityConfig() - } + bootstrap: [ + getDefaultServerSecurityConfig() + ] }; } 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 dcc599bc41..47ad830c33 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1310,16 +1310,18 @@ "edit-attribute": "Edit attribute", "view-attribute": "View attribute", "remove-attribute": "Remove attribute", + "delete-server-text": "Be careful, after the confirmation the server configuration will become unrecoverable.", + "delete-server-title": "Are you sure you want to delete the server?", "mode": "Security config mode", "bootstrap-tab": "Bootstrap", "bootstrap-server-legend": "Bootstrap Server (ShortId...)", "lwm2m-server-legend": "LwM2M Server (ShortId...)", "server": "Server", - "short-id": "Short ID", - "short-id-tooltip": "Server ShortID must be equal Security ShortID ", - "short-id-required": "Short ID is required.", - "short-id-range": "Short ID should be in a range from 1 to 65534.", - "short-id-pattern": "Short ID must be a positive integer.", + "short-id": "Short server ID", + "short-id-tooltip": "Server short Id. Used as link to associate server Object Instance.\nThis identifier uniquely identifies each LwM2M Server configured for the LwM2M Client.\nResource MUST be set when the Bootstrap-Server Resource has a value of 'false'.\nThe values ID:0 and ID:65535 values MUST NOT be used for identifying the LwM2M Server.", + "short-id-required": "Short server ID is required.", + "short-id-range": "Short server ID should be in a range from 1 to 65534.", + "short-id-pattern": "Short server ID must be a positive integer.", "lifetime": "Client registration lifetime", "lifetime-required": "Client registration lifetime is required.", "lifetime-pattern": "Client registration lifetime must be a positive integer.", @@ -1361,6 +1363,11 @@ "account-after-timeout-required": "Account after the timeout is required.", "account-after-timeout-pattern": "Account after the timeout must be a positive integer.", "account-after-timeout-tooltip": "Bootstrap-Server Account after the timeout value given by this resource.", + "server-type": "Server type", + "add-new-server-title": "Add new server config", + "add-server-config": "Add server config", + "add-lwm2m-server-config": "Add LwM2M server", + "no-config-servers": "No servers configured", "others-tab": "Other settings", "client-strategy": "Client strategy when connecting", "client-strategy-label": "Strategy",