Browse Source

Bootstrap servers refactoring for LwM2M transport

pull/5558/head
Sergey Tarnavskiy 5 years ago
parent
commit
25abfcebf3
  1. 1
      ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html
  2. 4
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html
  3. 1
      ui-ngx/src/app/modules/home/components/profile/device-profile.component.html
  4. 3
      ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts
  5. 1
      ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html
  6. 3
      ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.ts
  7. 55
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.html
  8. 60
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.ts
  9. 39
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html
  10. 185
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.ts
  11. 257
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html
  12. 44
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts
  13. 90
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html
  14. 56
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts
  15. 6
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-components.module.ts
  16. 66
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts
  17. 1
      ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html
  18. 1
      ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html
  19. 5
      ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts
  20. 9
      ui-ngx/src/app/shared/models/device.models.ts
  21. 14
      ui-ngx/src/app/shared/models/lwm2m-security-config.models.ts
  22. 17
      ui-ngx/src/assets/locale/locale.constant-en_US.json

1
ui-ngx/src/app/modules/home/components/profile/add-device-profile-dialog.component.html

@ -100,6 +100,7 @@
</mat-form-field> </mat-form-field>
<tb-device-profile-transport-configuration <tb-device-profile-transport-configuration
formControlName="transportConfiguration" formControlName="transportConfiguration"
isAdd="true"
required> required>
</tb-device-profile-transport-configuration> </tb-device-profile-transport-configuration>
</form> </form>

4
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html

@ -34,9 +34,7 @@
<div *ngIf="!disabled" style="padding-top: 16px;"> <div *ngIf="!disabled" style="padding-top: 16px;">
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
type="button" type="button"
(click)="addAlarm()" (click)="addAlarm()">
matTooltip="{{ 'device-profile.add-alarm-rule' | translate }}"
matTooltipPosition="above">
<span translate>device-profile.add-alarm-rule</span> <span translate>device-profile.add-alarm-rule</span>
</button> </button>
</div> </div>

1
ui-ngx/src/app/modules/home/components/profile/device-profile.component.html

@ -138,6 +138,7 @@
<ng-template matExpansionPanelContent> <ng-template matExpansionPanelContent>
<tb-device-profile-transport-configuration <tb-device-profile-transport-configuration
formControlName="transportConfiguration" formControlName="transportConfiguration"
[isAdd] = "isTransportTypeChanged"
required> required>
</tb-device-profile-transport-configuration> </tb-device-profile-transport-configuration>
</ng-template> </ng-template>

3
ui-ngx/src/app/modules/home/components/profile/device-profile.component.ts

@ -67,6 +67,8 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
displayTransportConfiguration: boolean; displayTransportConfiguration: boolean;
isTransportTypeChanged = false;
serviceType = ServiceType.TB_RULE_ENGINE; serviceType = ServiceType.TB_RULE_ENGINE;
deviceProfileId: EntityId; deviceProfileId: EntityId;
@ -158,6 +160,7 @@ export class DeviceProfileComponent extends EntityComponent<DeviceProfile> {
const deviceTransportType: DeviceTransportType = form.get('transportType').value; const deviceTransportType: DeviceTransportType = form.get('transportType').value;
this.displayTransportConfiguration = deviceTransportType && this.displayTransportConfiguration = deviceTransportType &&
deviceTransportTypeConfigurationInfoMap.get(deviceTransportType).hasProfileConfiguration; deviceTransportTypeConfigurationInfoMap.get(deviceTransportType).hasProfileConfiguration;
this.isTransportTypeChanged = true;
let profileData: DeviceProfileData = form.getRawValue().profileData; let profileData: DeviceProfileData = form.getRawValue().profileData;
if (!profileData) { if (!profileData) {
profileData = { profileData = {

1
ui-ngx/src/app/modules/home/components/profile/device/device-profile-transport-configuration.component.html

@ -37,6 +37,7 @@
</ng-template> </ng-template>
<ng-template [ngSwitchCase]="deviceTransportType.LWM2M"> <ng-template [ngSwitchCase]="deviceTransportType.LWM2M">
<tb-profile-lwm2m-device-transport-configuration <tb-profile-lwm2m-device-transport-configuration
[isAdd]="isAdd"
[required]="required" [required]="required"
formControlName="configuration"> formControlName="configuration">
</tb-profile-lwm2m-device-transport-configuration> </tb-profile-lwm2m-device-transport-configuration>

3
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() @Input()
disabled: boolean; disabled: boolean;
@Input()
isAdd: boolean;
transportType: DeviceTransportType; transportType: DeviceTransportType;
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };

55
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-add-config-server-dialog.component.html

@ -0,0 +1,55 @@
<!--
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.
-->
<form [formGroup]="addConfigServerFormGroup" style="width: 400px;">
<mat-toolbar fxLayout="row" color="primary">
<h2 translate>device-profile.lwm2m.add-new-server-title</h2>
<span fxFlex></span>
<button mat-button mat-icon-button (click)="cancel()" type="button">
<mat-icon class="material-icons">close</mat-icon>
</button>
</mat-toolbar>
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<div mat-dialog-content fxLayout="column">
<mat-form-field>
<mat-label>{{ 'device-profile.lwm2m.server-type' | translate }}</mat-label>
<mat-select formControlName="serverType">
<mat-option *ngFor="let serverType of serverTypes"
[value]="serverType">
{{ serverConfigTypeNamesMap.get(serverType) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div mat-dialog-actions fxLayout="row">
<span fxFlex></span>
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
<button mat-button mat-raised-button color="primary"
type="button"
[disabled]="(isLoading$ | async) || addConfigServerFormGroup.invalid"
(click)="addServerConfig()">
{{ 'action.add' | translate }}
</button>
</div>
</form>

60
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<Lwm2mBootstrapAddConfigServerDialogComponent> {
addConfigServerFormGroup: FormGroup;
serverTypes = Object.values(ServerConfigType);
serverConfigTypeNamesMap = ServerConfigTypeTranslationMap;
constructor(protected store: Store<AppState>,
protected router: Router,
private fb: FormBuilder,
public dialogRef: MatDialogRef<Lwm2mBootstrapAddConfigServerDialogComponent, boolean>,
) {
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);
}
}

39
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-bootstrap-config-servers.component.html

@ -0,0 +1,39 @@
<!--
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.
-->
<div fxLayout="column">
<mat-accordion multi="true">
<div *ngFor="let serverConfig of serverConfigsFromArray().controls; trackBy: trackByParams; let $index = index;">
<tb-profile-lwm2m-device-config-server
[formControl]="serverConfig"
(removeServer)="removeServerConfig($event, $index)">
</tb-profile-lwm2m-device-config-server>
</div>
</mat-accordion>
<div *ngIf="!serverConfigsFromArray().controls.length" style="margin:32px 0">
<span translate fxLayoutAlign="center center"
class="tb-prompt">device-profile.lwm2m.no-config-servers</span>
</div>
<div *ngIf="!disabled" style="padding-top: 16px;">
<button mat-raised-button color="primary"
type="button"
(click)="addServerConfig()">
<span>{{ (isBootstrapAdded() ? 'device-profile.lwm2m.add-lwm2m-server-config' :
'device-profile.lwm2m.add-server-config') | translate}}</span>
</button>
</div>
</div>

185
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<ServerSecurityConfig> | null): void {
if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe();
}
const serverConfigsControls: Array<AbstractControl> = [];
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>(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<ServerSecurityConfig> = this.serverConfigsFromArray().value;
this.propagateChange(serverConfigs);
}
}

257
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.html

@ -15,99 +15,170 @@
limitations under the License. limitations under the License.
--> -->
<section [formGroup]="serverFormGroup"> <mat-expansion-panel [formGroup]="serverFormGroup" #serverPanel>
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px"> <mat-expansion-panel-header>
<mat-form-field fxFlex> <div fxFlex fxLayout="row" fxLayoutAlign="start center">
<mat-label>{{ 'device-profile.lwm2m.mode' | translate }}</mat-label> <mat-panel-title>
<mat-select formControlName="securityMode"> <div fxLayout="row" fxFlex fxLayoutAlign="start center">
<mat-option *ngFor="let securityMode of securityConfigLwM2MTypes" <div style="min-width:150px">{{ (serverFormGroup.get('bootstrapServerIs').value ?
[value]="securityMode"> 'device-profile.lwm2m.bootstrap-server' : 'device-profile.lwm2m.lwm2m-server') | translate }}</div>
{{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityMode]) }} <div *ngIf="!serverPanel.expanded" fxLayout="row" style="font-size:14px">
</mat-option> <div style="margin-left:32px">{{ ('device-profile.lwm2m.short-id' | translate) + ': ' }}
</mat-select> <span style="font-style: italic">{{ serverFormGroup.get('shortServerId').value }}</span>
</mat-form-field> </div>
<mat-form-field fxFlex> <div style="margin-left:32px">{{ ('device-profile.lwm2m.mode' | translate) + ': ' }}
<mat-label>{{ 'device-profile.lwm2m.server-host' | translate }}</mat-label> <span style="font-style: italic">{{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[serverFormGroup.get('securityMode').value]) }}</span>
<input matInput type="text" formControlName="host" required> </div>
<mat-error *ngIf="serverFormGroup.get('host').hasError('required')"> </div>
{{ 'device-profile.lwm2m.server-host-required' | translate }} </div>
</mat-error> </mat-panel-title>
</mat-form-field> <span fxFlex></span>
<mat-form-field fxFlex> <button *ngIf="!disabled" mat-icon-button style="min-width: 40px;"
<mat-label>{{ 'device-profile.lwm2m.server-port' | translate }}</mat-label> type="button"
<input matInput type="number" formControlName="port" required min="0" max="65535"> (click)="removeServer.emit($event)"
<mat-error *ngIf="serverFormGroup.get('port').hasError('required')"> matTooltip="{{ 'action.remove' | translate }}"
{{ 'device-profile.lwm2m.server-port-required' | translate }} matTooltipPosition="above">
</mat-error> <mat-icon>delete</mat-icon>
<mat-error *ngIf="serverFormGroup.get('port').hasError('pattern')"> </button>
{{ 'device-profile.lwm2m.server-port-pattern' | translate }} </div>
</mat-error> </mat-expansion-panel-header>
<mat-error *ngIf="serverFormGroup.get('port').hasError('min') || <ng-template matExpansionPanelContent>
<section>
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.mode' | translate }}</mat-label>
<mat-select formControlName="securityMode">
<mat-option *ngFor="let securityMode of securityConfigLwM2MTypes"
[value]="securityMode">
{{ credentialTypeLwM2MNamesMap.get(securityConfigLwM2MType[securityMode]) }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.short-id' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.short-id-tooltip' | translate }}">help</mat-icon>
<input matInput type="number" min="1" max="65534" formControlName="shortServerId" required>
<mat-error *ngIf="serverFormGroup.get('shortServerId').hasError('required')">
{{ 'device-profile.lwm2m.short-id-required' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('shortServerId').hasError('pattern')">
{{ 'device-profile.lwm2m.short-id-pattern' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('shortServerId').hasError('min') ||
serverFormGroup.get('shortServerId').hasError('max')">
{{ 'device-profile.lwm2m.short-id-range' | translate }}
</mat-error>
</mat-form-field>
</div>
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.server-host' | translate }}</mat-label>
<input matInput type="text" formControlName="host" required>
<mat-error *ngIf="serverFormGroup.get('host').hasError('required')">
{{ 'device-profile.lwm2m.server-host-required' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.server-port' | translate }}</mat-label>
<input matInput type="number" formControlName="port" required min="0" max="65535" readonly>
<mat-error *ngIf="serverFormGroup.get('port').hasError('required')">
{{ 'device-profile.lwm2m.server-port-required' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('port').hasError('pattern')">
{{ 'device-profile.lwm2m.server-port-pattern' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('port').hasError('min') ||
serverFormGroup.get('port').hasError('max')"> serverFormGroup.get('port').hasError('max')">
{{ 'device-profile.lwm2m.server-port-range' | translate }} {{ 'device-profile.lwm2m.server-port-range' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px"> <div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px">
<mat-form-field fxFlex> <mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.short-id' | translate }}</mat-label> <mat-label>{{ 'device-profile.lwm2m.client-hold-off-time' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;" <mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.short-id-tooltip' | translate }}">help</mat-icon> matTooltip="{{'device-profile.lwm2m.client-hold-off-time-tooltip' | translate }}">help</mat-icon>
<input matInput type="number" min="1" max="65534" formControlName="serverId" required> <input matInput type="number" formControlName="clientHoldOffTime" required min="0">
<mat-error *ngIf="serverFormGroup.get('serverId').hasError('required')"> <mat-error *ngIf="serverFormGroup.get('clientHoldOffTime').hasError('required')">
{{ 'device-profile.lwm2m.short-id-required' | translate }} {{ 'device-profile.lwm2m.client-hold-off-time-required' | translate }}
</mat-error> </mat-error>
<mat-error *ngIf="serverFormGroup.get('serverId').hasError('pattern')"> <mat-error *ngIf="serverFormGroup.get('clientHoldOffTime').hasError('min') ||
{{ 'device-profile.lwm2m.short-id-pattern' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('serverId').hasError('min') ||
serverFormGroup.get('serverId').hasError('max')">
{{ 'device-profile.lwm2m.short-id-range' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.client-hold-off-time' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.client-hold-off-time-tooltip' | translate }}">help</mat-icon>
<input matInput type="number" formControlName="clientHoldOffTime" required min="0">
<mat-error *ngIf="serverFormGroup.get('clientHoldOffTime').hasError('required')">
{{ 'device-profile.lwm2m.client-hold-off-time-required' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('clientHoldOffTime').hasError('min') ||
serverFormGroup.get('clientHoldOffTime').hasError('pattern')"> serverFormGroup.get('clientHoldOffTime').hasError('pattern')">
{{ 'device-profile.lwm2m.client-hold-off-time-pattern' | translate }} {{ 'device-profile.lwm2m.client-hold-off-time-pattern' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field fxFlex> <mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.account-after-timeout' | translate }}</mat-label> <mat-label>{{ 'device-profile.lwm2m.account-after-timeout' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;" <mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.account-after-timeout-tooltip' | translate }}">help</mat-icon> matTooltip="{{'device-profile.lwm2m.account-after-timeout-tooltip' | translate }}">help</mat-icon>
<input matInput type="number" formControlName="bootstrapServerAccountTimeout" required min="0"> <input matInput type="number" formControlName="bootstrapServerAccountTimeout" required min="0">
<mat-error *ngIf="serverFormGroup.get('bootstrapServerAccountTimeout').hasError('required')"> <mat-error *ngIf="serverFormGroup.get('bootstrapServerAccountTimeout').hasError('required')">
{{ 'device-profile.lwm2m.account-after-timeout-required' | translate }} {{ 'device-profile.lwm2m.account-after-timeout-required' | translate }}
</mat-error> </mat-error>
<mat-error *ngIf="serverFormGroup.get('bootstrapServerAccountTimeout').hasError('min') || <mat-error *ngIf="serverFormGroup.get('bootstrapServerAccountTimeout').hasError('min') ||
serverFormGroup.get('bootstrapServerAccountTimeout').hasError('pattern')"> serverFormGroup.get('bootstrapServerAccountTimeout').hasError('pattern')">
{{ 'device-profile.lwm2m.account-after-timeout-pattern' | translate }} {{ 'device-profile.lwm2m.account-after-timeout-pattern' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
<div *ngIf="serverFormGroup.get('securityMode').value === securityConfigLwM2MType.RPK || <div *ngIf="serverFormGroup.get('securityMode').value === securityConfigLwM2MType.RPK ||
serverFormGroup.get('securityMode').value === securityConfigLwM2MType.X509"> serverFormGroup.get('securityMode').value === securityConfigLwM2MType.X509">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.server-public-key' | translate }}</mat-label> <mat-label>{{ 'device-profile.lwm2m.server-public-key' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;" <mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{ publicKeyOrIdTooltipNamesMap.get(serverFormGroup.get('securityMode').value) | translate }}">help</mat-icon> matTooltip="{{ publicKeyOrIdTooltipNamesMap.get(serverFormGroup.get('securityMode').value) | translate }}">help</mat-icon>
<textarea matInput <textarea matInput
cdkTextareaAutosize cdkTextareaAutosize
cdkAutosizeMinRows="1" cdkAutosizeMinRows="1"
cols="1" required cols="1" required
formControlName="serverPublicKey" formControlName="serverPublicKey"
required> required>
</textarea> </textarea>
<mat-error *ngIf="serverFormGroup.get('serverPublicKey').hasError('required')"> <mat-error *ngIf="serverFormGroup.get('serverPublicKey').hasError('required')">
{{ 'device-profile.lwm2m.server-public-key-required' | translate }} {{ 'device-profile.lwm2m.server-public-key-required' | translate }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</div> </div>
</section> <div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.lifetime' | translate }}</mat-label>
<input matInput type="number" min="0" formControlName="lifetime" required>
<mat-error *ngIf="serverFormGroup.get('lifetime').hasError('required')">
{{ 'device-profile.lwm2m.lifetime-required' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('lifetime').hasError('pattern') ||
serverFormGroup.get('lifetime').hasError('min')">
{{ 'device-profile.lwm2m.lifetime-pattern' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.default-min-period' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.default-min-period-tooltip' | translate }}">help</mat-icon>
<input matInput type="number" min="0" formControlName="defaultMinPeriod" required>
<mat-error *ngIf="serverFormGroup.get('defaultMinPeriod').hasError('required')">
{{ 'device-profile.lwm2m.default-min-period-required' | translate }}
</mat-error>
<mat-error *ngIf="serverFormGroup.get('defaultMinPeriod').hasError('pattern') ||
serverFormGroup.get('defaultMinPeriod').hasError('min')">
{{ 'device-profile.lwm2m.default-min-period-pattern' | translate }}
</mat-error>
</mat-form-field>
</div>
<mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.binding' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.binding-tooltip' | translate }}">help</mat-icon>
<mat-select formControlName="binding">
<mat-option *ngFor="let bindingMode of bindingModeTypes" [value]="bindingMode">
{{ bindingModeTypeNamesMap.get(bindingMode) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-checkbox formControlName="notifIfDisabled" color="primary">
{{ 'device-profile.lwm2m.notification-storing' | translate }}
</mat-checkbox>
</section>
</ng-template>
</mat-expansion-panel>

44
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-config-server.component.ts

@ -14,7 +14,7 @@
/// limitations under the License. /// 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 { import {
ControlValueAccessor, ControlValueAccessor,
FormBuilder, FormBuilder,
@ -26,8 +26,7 @@ import {
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { import {
DEFAULT_PORT_BOOTSTRAP_NO_SEC, BingingMode, BingingModeTranslationsMap,
DEFAULT_PORT_SERVER_NO_SEC,
ServerSecurityConfig ServerSecurityConfig
} from './lwm2m-profile-config.models'; } from './lwm2m-profile-config.models';
import { DeviceProfileService } from '@core/http/device-profile.service'; import { DeviceProfileService } from '@core/http/device-profile.service';
@ -65,14 +64,16 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
private isDataLoadedIntoCache = false; private isDataLoadedIntoCache = false;
serverFormGroup: FormGroup; serverFormGroup: FormGroup;
bindingModeTypes = Object.values(BingingMode);
bindingModeTypeNamesMap = BingingModeTranslationsMap;
securityConfigLwM2MType = Lwm2mSecurityType; securityConfigLwM2MType = Lwm2mSecurityType;
securityConfigLwM2MTypes = Object.keys(Lwm2mSecurityType); securityConfigLwM2MTypes = Object.keys(Lwm2mSecurityType);
credentialTypeLwM2MNamesMap = Lwm2mSecurityTypeTranslationMap; credentialTypeLwM2MNamesMap = Lwm2mSecurityTypeTranslationMap;
publicKeyOrIdTooltipNamesMap = Lwm2mPublicKeyOrIdTooltipTranslationsMap; publicKeyOrIdTooltipNamesMap = Lwm2mPublicKeyOrIdTooltipTranslationsMap;
currentSecurityMode = null; currentSecurityMode = null;
@Input() @Output()
isBootstrapServer = false; removeServer = new EventEmitter();
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };
@ -83,19 +84,29 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
ngOnInit(): void { ngOnInit(): void {
this.serverFormGroup = this.fb.group({ this.serverFormGroup = this.fb.group({
host: ['', Validators.required], host: ['', Validators.required],
port: [this.isBootstrapServer ? DEFAULT_PORT_BOOTSTRAP_NO_SEC : DEFAULT_PORT_SERVER_NO_SEC, port: ['', [Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]],
[Validators.required, Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*')]],
securityMode: [Lwm2mSecurityType.NO_SEC], securityMode: [Lwm2mSecurityType.NO_SEC],
serverPublicKey: [''], serverPublicKey: [''],
clientHoldOffTime: ['', [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], 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]*')]], 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( this.serverFormGroup.get('securityMode').valueChanges.pipe(
tap(securityMode => this.updateValidate(securityMode)), tap((securityMode) => {
this.currentSecurityMode = securityMode;
this.updateValidate(securityMode);
}),
mergeMap(securityMode => this.getLwm2mBootstrapSecurityInfo(securityMode)), mergeMap(securityMode => this.getLwm2mBootstrapSecurityInfo(securityMode)),
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe(serverSecurityConfig => { ).subscribe(serverSecurityConfig => {
if (this.currentSecurityMode !== Lwm2mSecurityType.NO_SEC) {
this.changeSecurityHostPortFields(serverSecurityConfig);
}
this.serverFormGroup.patchValue(serverSecurityConfig, {emitEvent: false}); this.serverFormGroup.patchValue(serverSecurityConfig, {emitEvent: false});
}); });
this.serverFormGroup.valueChanges.pipe( this.serverFormGroup.valueChanges.pipe(
@ -114,8 +125,13 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
if (serverData) { if (serverData) {
this.serverFormGroup.patchValue(serverData, {emitEvent: false}); this.serverFormGroup.patchValue(serverData, {emitEvent: false});
this.updateValidate(serverData.securityMode); 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 => { this.getLwm2mBootstrapSecurityInfo().subscribe(value => {
if (!serverData) { if (!serverData) {
this.serverFormGroup.patchValue(value); this.serverFormGroup.patchValue(value);
@ -171,11 +187,17 @@ export class Lwm2mDeviceConfigServerComponent implements OnInit, ControlValueAcc
} }
private getLwm2mBootstrapSecurityInfo(securityMode = Lwm2mSecurityType.NO_SEC): Observable<ServerSecurityConfig> { private getLwm2mBootstrapSecurityInfo(securityMode = Lwm2mSecurityType.NO_SEC): Observable<ServerSecurityConfig> {
return this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(this.isBootstrapServer, securityMode).pipe( return this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(
this.serverFormGroup.get('bootstrapServerIs').value, securityMode).pipe(
tap(() => this.isDataLoadedIntoCache = true) tap(() => this.isDataLoadedIntoCache = true)
); );
} }
private changeSecurityHostPortFields(serverData: ServerSecurityConfig): void {
serverData.port = serverData.securityPort;
serverData.host = serverData.securityHost;
}
validate(): ValidationErrors | null { validate(): ValidationErrors | null {
return this.serverFormGroup.valid ? null : { return this.serverFormGroup.valid ? null : {
serverFormGroup: true serverFormGroup: true

90
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html

@ -33,93 +33,9 @@
</mat-tab> </mat-tab>
<mat-tab label="{{ 'device-profile.lwm2m.bootstrap-tab' | translate }}"> <mat-tab label="{{ 'device-profile.lwm2m.bootstrap-tab' | translate }}">
<section [formGroup]="lwm2mDeviceProfileFormGroup"> <section [formGroup]="lwm2mDeviceProfileFormGroup">
<section formGroupName="bootstrap" style="padding: 20px 2px"> <section style="padding: 20px 2px">
<mat-accordion multi="true"> <tb-profile-lwm2m-bootstrap-config-servers formControlName="bootstrap">
<mat-expansion-panel> </tb-profile-lwm2m-bootstrap-config-servers>
<mat-expansion-panel-header>
<mat-panel-title>{{ 'device-profile.lwm2m.server' | translate }}</mat-panel-title>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent formGroupName="servers">
<div fxLayout="row" fxLayout.xs="column" fxLayoutGap="8px" fxLayoutGap.xs="0px">
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.short-id' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.short-id-tooltip' | translate }}">help</mat-icon>
<input matInput type="number" min="1" max="65534" formControlName="shortId" required>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('bootstrap.servers.shortId').hasError('required')">
{{ 'device-profile.lwm2m.short-id-required' | translate }}
</mat-error>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('bootstrap.servers.shortId').hasError('min') ||
lwm2mDeviceProfileFormGroup.get('bootstrap.servers.shortId').hasError('max')">
{{ 'device-profile.lwm2m.short-id-range' | translate }}
</mat-error>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('bootstrap.servers.shortId').hasError('pattern')">
{{ 'device-profile.lwm2m.short-id-pattern' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.lifetime' | translate }}</mat-label>
<input matInput type="number" min="0" formControlName="lifetime" required>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('bootstrap.servers.lifetime').hasError('required')">
{{ 'device-profile.lwm2m.lifetime-required' | translate }}
</mat-error>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('bootstrap.servers.lifetime').hasError('pattern') ||
lwm2mDeviceProfileFormGroup.get('bootstrap.servers.lifetime').hasError('min')">
{{ 'device-profile.lwm2m.lifetime-pattern' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field fxFlex>
<mat-label>{{ 'device-profile.lwm2m.default-min-period' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.default-min-period-tooltip' | translate }}">help</mat-icon>
<input matInput type="number" min="0" formControlName="defaultMinPeriod" required>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('bootstrap.servers.defaultMinPeriod').hasError('required')">
{{ 'device-profile.lwm2m.default-min-period-required' | translate }}
</mat-error>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('bootstrap.servers.defaultMinPeriod').hasError('pattern') ||
lwm2mDeviceProfileFormGroup.get('bootstrap.servers.defaultMinPeriod').hasError('min')">
{{ 'device-profile.lwm2m.default-min-period-pattern' | translate }}
</mat-error>
</mat-form-field>
</div>
<mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.binding' | translate }}</mat-label>
<mat-icon *ngIf="!disabled" class="mat-primary" aria-hidden="false" aria-label="help-icon" matSuffix style="cursor:pointer;"
matTooltip="{{'device-profile.lwm2m.binding-tooltip' | translate }}">help</mat-icon>
<mat-select formControlName="binding">
<mat-option *ngFor="let bindingMode of bindingModeTypes" [value]="bindingMode">
{{ bindingModeTypeNamesMap.get(bindingMode) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-checkbox formControlName="notifIfDisabled" color="primary">
{{ 'device-profile.lwm2m.notification-storing' | translate }}
</mat-checkbox>
</ng-template>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>{{ 'device-profile.lwm2m.bootstrap-server' | translate }}</mat-panel-title>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-profile-lwm2m-device-config-server
formControlName="bootstrapServer"
[isBootstrapServer]="true">
</tb-profile-lwm2m-device-config-server>
</ng-template>
</mat-expansion-panel>
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>{{ 'device-profile.lwm2m.lwm2m-server' | translate }}</mat-panel-title>
</mat-expansion-panel-header>
<ng-template matExpansionPanelContent>
<tb-profile-lwm2m-device-config-server
formControlName="lwm2mServer"
[isBootstrapServer]="false">
</tb-profile-lwm2m-device-config-server>
</ng-template>
</mat-expansion-panel>
</mat-accordion>
</section> </section>
</section> </section>
</mat-tab> </mat-tab>

56
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 { coerceBooleanProperty } from '@angular/cdk/coercion';
import { import {
ATTRIBUTE, ATTRIBUTE,
BingingMode,
BingingModeTranslationsMap,
DEFAULT_BINDING,
DEFAULT_EDRX_CYCLE, DEFAULT_EDRX_CYCLE,
DEFAULT_FW_UPDATE_RESOURCE, DEFAULT_FW_UPDATE_RESOURCE,
DEFAULT_ID_SERVER,
DEFAULT_LIFE_TIME,
DEFAULT_MIN_PERIOD,
DEFAULT_NOTIF_IF_DESIBLED,
DEFAULT_PAGING_TRANSMISSION_WINDOW, DEFAULT_PAGING_TRANSMISSION_WINDOW,
DEFAULT_PSM_ACTIVITY_TIMER, DEFAULT_PSM_ACTIVITY_TIMER,
DEFAULT_SW_UPDATE_RESOURCE, DEFAULT_SW_UPDATE_RESOURCE,
getDefaultBootstrapServerSecurityConfig,
getDefaultLwM2MServerSecurityConfig,
Instance, Instance,
INSTANCES, INSTANCES,
KEY_NAME, KEY_NAME,
@ -60,6 +51,7 @@ import { Direction } from '@shared/models/page/sort-order';
import _ from 'lodash'; import _ from 'lodash';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { Lwm2mSecurityType } from '@shared/models/lwm2m-security-config.models';
@Component({ @Component({
selector: 'tb-profile-lwm2m-device-transport-configuration', selector: 'tb-profile-lwm2m-device-transport-configuration',
@ -83,8 +75,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
private requiredValue: boolean; private requiredValue: boolean;
private destroy$ = new Subject(); private destroy$ = new Subject();
bindingModeTypes = Object.values(BingingMode);
bindingModeTypeNamesMap = BingingModeTranslationsMap;
lwm2mDeviceProfileFormGroup: FormGroup; lwm2mDeviceProfileFormGroup: FormGroup;
configurationValue: Lwm2mProfileConfigModels; configurationValue: Lwm2mProfileConfigModels;
sortFunction: (key: string, value: object) => object; sortFunction: (key: string, value: object) => object;
@ -98,6 +88,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
this.requiredValue = coerceBooleanProperty(value); this.requiredValue = coerceBooleanProperty(value);
} }
@Input()
isAdd: boolean;
private propagateChange = (v: any) => { private propagateChange = (v: any) => {
} }
@ -106,17 +99,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
this.lwm2mDeviceProfileFormGroup = this.fb.group({ this.lwm2mDeviceProfileFormGroup = this.fb.group({
objectIds: [null], objectIds: [null],
observeAttrTelemetry: [null], observeAttrTelemetry: [null],
bootstrap: this.fb.group({ bootstrap: [[]],
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]
}),
clientLwM2mSettings: this.fb.group({ clientLwM2mSettings: this.fb.group({
clientOnlyObserveAfterConnect: [1, []], clientOnlyObserveAfterConnect: [1, []],
fwUpdateStrategy: [1, []], fwUpdateStrategy: [1, []],
@ -187,9 +170,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
async writeValue(value: Lwm2mProfileConfigModels | null) { async writeValue(value: Lwm2mProfileConfigModels | null) {
if (isDefinedAndNotNull(value) && (value?.clientLwM2mSettings || value?.observeAttr || value?.bootstrap)) { if (isDefinedAndNotNull(value) && (value?.clientLwM2mSettings || value?.observeAttr || value?.bootstrap)) {
this.configurationValue = value; this.configurationValue = value;
const defaultFormSettings = value.clientLwM2mSettings.fwUpdateStrategy === 1 && if (this.isAdd) {
isUndefined(value.clientLwM2mSettings.fwUpdateResource);
if (defaultFormSettings) {
await this.defaultProfileConfig(); await this.defaultProfileConfig();
} }
this.initWriteValue(); this.initWriteValue();
@ -203,23 +184,14 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
} }
private async defaultProfileConfig(): Promise<void> { private async defaultProfileConfig(): Promise<void> {
let bootstrap: ServerSecurityConfig; const lwm2m: ServerSecurityConfig = await this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(false).toPromise();
let lwm2m: ServerSecurityConfig; if (lwm2m) {
try { lwm2m.securityMode = Lwm2mSecurityType.NO_SEC;
[bootstrap, lwm2m] = await Promise.all([
this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(true).toPromise(),
this.deviceProfileService.getLwm2mBootstrapSecurityInfoBySecurityType(false).toPromise()
]);
} catch (e) {
bootstrap = getDefaultBootstrapServerSecurityConfig();
lwm2m = getDefaultLwM2MServerSecurityConfig();
} }
this.configurationValue.bootstrap = [lwm2m];
this.configurationValue.bootstrap.bootstrapServer = bootstrap;
this.configurationValue.bootstrap.lwm2mServer = lwm2m;
this.lwm2mDeviceProfileFormGroup.patchValue({ this.lwm2mDeviceProfileFormGroup.patchValue({
bootstrap: this.configurationValue.bootstrap bootstrap: this.configurationValue.bootstrap
}, {emitEvent: false}); }, {emitEvent: true});
} }
private initWriteValue = (): void => { private initWriteValue = (): void => {
@ -282,12 +254,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
} }
private updateDeviceProfileValue(config): void { private updateDeviceProfileValue(config): void {
if (this.lwm2mDeviceProfileFormGroup.valid) { if (this.lwm2mDeviceProfileFormGroup.valid && config.observeAttrTelemetry) {
this.updateObserveAttrTelemetryFromGroupToJson(config.observeAttrTelemetry); this.updateObserveAttrTelemetryFromGroupToJson(config.observeAttrTelemetry);
} }
this.configurationValue.bootstrap.bootstrapServer = config.bootstrap.bootstrapServer; this.configurationValue.bootstrap = config.bootstrap;
this.configurationValue.bootstrap.lwm2mServer = config.bootstrap.lwm2mServer;
this.configurationValue.bootstrap.servers = config.bootstrap.servers;
this.configurationValue.clientLwM2mSettings = config.clientLwM2mSettings; this.configurationValue.clientLwM2mSettings = config.clientLwM2mSettings;
this.updateModel(); this.updateModel();
} }

6
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 { Lwm2mAttributesDialogComponent } from './lwm2m-attributes-dialog.component';
import { Lwm2mAttributesComponent } from './lwm2m-attributes.component'; import { Lwm2mAttributesComponent } from './lwm2m-attributes.component';
import { Lwm2mAttributesKeyListComponent } from './lwm2m-attributes-key-list.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 { 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 { Lwm2mObjectAddInstancesDialogComponent } from './lwm2m-object-add-instances-dialog.component';
import { Lwm2mObjectAddInstancesListComponent } from './lwm2m-object-add-instances-list.component'; import { Lwm2mObjectAddInstancesListComponent } from './lwm2m-object-add-instances-list.component';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@ -40,7 +42,9 @@ import { DeviceProfileCommonModule } from '@home/components/profile/device/commo
Lwm2mAttributesDialogComponent, Lwm2mAttributesDialogComponent,
Lwm2mAttributesComponent, Lwm2mAttributesComponent,
Lwm2mAttributesKeyListComponent, Lwm2mAttributesKeyListComponent,
Lwm2mBootstrapConfigServersComponent,
Lwm2mDeviceConfigServerComponent, Lwm2mDeviceConfigServerComponent,
Lwm2mBootstrapAddConfigServerDialogComponent,
Lwm2mObjectAddInstancesDialogComponent, Lwm2mObjectAddInstancesDialogComponent,
Lwm2mObjectAddInstancesListComponent, Lwm2mObjectAddInstancesListComponent,
Lwm2mObserveAttrTelemetryInstancesComponent Lwm2mObserveAttrTelemetryInstancesComponent
@ -58,7 +62,9 @@ import { DeviceProfileCommonModule } from '@home/components/profile/device/commo
Lwm2mAttributesDialogComponent, Lwm2mAttributesDialogComponent,
Lwm2mAttributesComponent, Lwm2mAttributesComponent,
Lwm2mAttributesKeyListComponent, Lwm2mAttributesKeyListComponent,
Lwm2mBootstrapConfigServersComponent,
Lwm2mDeviceConfigServerComponent, Lwm2mDeviceConfigServerComponent,
Lwm2mBootstrapAddConfigServerDialogComponent,
Lwm2mObjectAddInstancesDialogComponent, Lwm2mObjectAddInstancesDialogComponent,
Lwm2mObjectAddInstancesListComponent, Lwm2mObjectAddInstancesListComponent,
Lwm2mObserveAttrTelemetryInstancesComponent Lwm2mObserveAttrTelemetryInstancesComponent

66
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts

@ -96,6 +96,18 @@ export const AttributeNameTranslationMap = new Map<AttributeName, string>(
] ]
); );
export enum ServerConfigType {
LWM2M = 'LWM2M',
BOOTSTRAP = 'BOOTSTRAP'
}
export const ServerConfigTypeTranslationMap = new Map<ServerConfigType, string>(
[
[ServerConfigType.LWM2M, 'device-profile.lwm2m.lwm2m-server'],
[ServerConfigType.BOOTSTRAP, 'device-profile.lwm2m.bootstrap-server']
]
);
export enum PowerMode { export enum PowerMode {
PSM = 'PSM', PSM = 'PSM',
DRX = 'DRX', DRX = 'DRX',
@ -110,22 +122,21 @@ export const PowerModeTranslationMap = new Map<PowerMode, string>(
] ]
); );
export interface BootstrapServersSecurityConfig {
shortId: number;
lifetime: number;
defaultMinPeriod: number;
notifIfDisabled: boolean;
binding: string;
}
export interface ServerSecurityConfig { export interface ServerSecurityConfig {
host?: string; host?: string;
port?: number; port?: number;
securityMode: Lwm2mSecurityType; securityMode: Lwm2mSecurityType;
securityHost?: string;
securityPort?: number;
serverPublicKey?: string; serverPublicKey?: string;
clientHoldOffTime?: number; clientHoldOffTime?: number;
serverId?: number; shortServerId?: number;
bootstrapServerAccountTimeout: number; bootstrapServerAccountTimeout: number;
lifetime: number;
defaultMinPeriod: number;
notifIfDisabled: boolean;
binding: string;
bootstrapServerIs: boolean;
} }
export interface ServerSecurityConfigInfo extends ServerSecurityConfig { export interface ServerSecurityConfigInfo extends ServerSecurityConfig {
@ -134,16 +145,10 @@ export interface ServerSecurityConfigInfo extends ServerSecurityConfig {
bootstrapServerIs: boolean; bootstrapServerIs: boolean;
} }
interface BootstrapSecurityConfig {
servers: BootstrapServersSecurityConfig;
bootstrapServer: ServerSecurityConfig;
lwm2mServer: ServerSecurityConfig;
}
export interface Lwm2mProfileConfigModels { export interface Lwm2mProfileConfigModels {
clientLwM2mSettings: ClientLwM2mSettings; clientLwM2mSettings: ClientLwM2mSettings;
observeAttr: ObservableAttributes; observeAttr: ObservableAttributes;
bootstrap: BootstrapSecurityConfig; bootstrap: Array<ServerSecurityConfig>;
} }
export interface ClientLwM2mSettings { export interface ClientLwM2mSettings {
@ -167,35 +172,6 @@ export interface ObservableAttributes {
attributeLwm2m: AttributesNameValueMap; 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 { export function getDefaultProfileObserveAttrConfig(): ObservableAttributes {
return { return {
observe: [], observe: [],

1
ui-ngx/src/app/modules/home/components/wizard/device-wizard-dialog.component.html

@ -133,6 +133,7 @@
</mat-form-field> </mat-form-field>
<tb-device-profile-transport-configuration <tb-device-profile-transport-configuration
formControlName="transportConfiguration" formControlName="transportConfiguration"
isAdd="true"
required> required>
</tb-device-profile-transport-configuration> </tb-device-profile-transport-configuration>
</form> </form>

1
ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.html

@ -35,6 +35,7 @@
<div formGroupName="profileData"> <div formGroupName="profileData">
<tb-device-profile-transport-configuration <tb-device-profile-transport-configuration
formControlName="transportConfiguration" formControlName="transportConfiguration"
[isAdd] = "isTransportTypeChanged"
required> required>
</tb-device-profile-transport-configuration> </tb-device-profile-transport-configuration>
</div> </div>

5
ui-ngx/src/app/modules/home/pages/device-profile/device-profile-tabs.component.ts

@ -38,12 +38,17 @@ export class DeviceProfileTabsComponent extends EntityTabsComponent<DeviceProfil
deviceTransportTypeHints = deviceTransportTypeHintMap; deviceTransportTypeHints = deviceTransportTypeHintMap;
isTransportTypeChanged = false;
constructor(protected store: Store<AppState>) { constructor(protected store: Store<AppState>) {
super(store); super(store);
} }
ngOnInit() { ngOnInit() {
super.ngOnInit(); super.ngOnInit();
this.detailsForm.get('transportType').valueChanges.subscribe(() => {
this.isTransportTypeChanged = true;
});
} }
} }

9
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 { DashboardId } from '@shared/models/id/dashboard-id';
import { DataType } from '@shared/models/constants'; import { DataType } from '@shared/models/constants';
import { import {
getDefaultBootstrapServerSecurityConfig,
getDefaultBootstrapServersSecurityConfig,
getDefaultLwM2MServerSecurityConfig,
getDefaultProfileClientLwM2mSettingsConfig, getDefaultProfileClientLwM2mSettingsConfig,
getDefaultProfileObserveAttrConfig, getDefaultProfileObserveAttrConfig,
PowerMode PowerMode
@ -384,11 +381,7 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT
case DeviceTransportType.LWM2M: case DeviceTransportType.LWM2M:
const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = { const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = {
observeAttr: getDefaultProfileObserveAttrConfig(), observeAttr: getDefaultProfileObserveAttrConfig(),
bootstrap: { bootstrap: [],
servers: getDefaultBootstrapServersSecurityConfig(),
bootstrapServer: getDefaultBootstrapServerSecurityConfig(),
lwm2mServer: getDefaultLwM2MServerSecurityConfig()
},
clientLwM2mSettings: getDefaultProfileClientLwM2mSettingsConfig() clientLwM2mSettings: getDefaultProfileClientLwM2mSettingsConfig()
}; };
transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M};

14
ui-ngx/src/app/shared/models/lwm2m-security-config.models.ts

@ -67,14 +67,9 @@ export interface ServerSecurityConfig {
clientSecretKey?: string; clientSecretKey?: string;
} }
interface BootstrapSecurityConfig {
bootstrapServer: ServerSecurityConfig;
lwm2mServer: ServerSecurityConfig;
}
export interface Lwm2mSecurityConfigModels { export interface Lwm2mSecurityConfigModels {
client: ClientSecurityConfig; client: ClientSecurityConfig;
bootstrap: BootstrapSecurityConfig; bootstrap: Array<ServerSecurityConfig>;
} }
@ -84,10 +79,9 @@ export function getLwm2mSecurityConfigModelsDefault(): Lwm2mSecurityConfigModels
securityConfigClientMode: Lwm2mSecurityType.NO_SEC, securityConfigClientMode: Lwm2mSecurityType.NO_SEC,
endpoint: '' endpoint: ''
}, },
bootstrap: { bootstrap: [
bootstrapServer: getDefaultServerSecurityConfig(), getDefaultServerSecurityConfig()
lwm2mServer: getDefaultServerSecurityConfig() ]
}
}; };
} }

17
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1310,16 +1310,18 @@
"edit-attribute": "Edit attribute", "edit-attribute": "Edit attribute",
"view-attribute": "View attribute", "view-attribute": "View attribute",
"remove-attribute": "Remove 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", "mode": "Security config mode",
"bootstrap-tab": "Bootstrap", "bootstrap-tab": "Bootstrap",
"bootstrap-server-legend": "Bootstrap Server (ShortId...)", "bootstrap-server-legend": "Bootstrap Server (ShortId...)",
"lwm2m-server-legend": "LwM2M Server (ShortId...)", "lwm2m-server-legend": "LwM2M Server (ShortId...)",
"server": "Server", "server": "Server",
"short-id": "Short ID", "short-id": "Short server ID",
"short-id-tooltip": "Server ShortID must be equal Security ShortID ", "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 ID is required.", "short-id-required": "Short server ID is required.",
"short-id-range": "Short ID should be in a range from 1 to 65534.", "short-id-range": "Short server ID should be in a range from 1 to 65534.",
"short-id-pattern": "Short ID must be a positive integer.", "short-id-pattern": "Short server ID must be a positive integer.",
"lifetime": "Client registration lifetime", "lifetime": "Client registration lifetime",
"lifetime-required": "Client registration lifetime is required.", "lifetime-required": "Client registration lifetime is required.",
"lifetime-pattern": "Client registration lifetime must be a positive integer.", "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-required": "Account after the timeout is required.",
"account-after-timeout-pattern": "Account after the timeout must be a positive integer.", "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.", "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", "others-tab": "Other settings",
"client-strategy": "Client strategy when connecting", "client-strategy": "Client strategy when connecting",
"client-strategy-label": "Strategy", "client-strategy-label": "Strategy",

Loading…
Cancel
Save