Browse Source

UI: Add power mode settings in LwM2M device profile and refactoring lwm2m device profile transport form

pull/4958/head
Vladyslav_Prykhodko 5 years ago
committed by Andrew Shvayka
parent
commit
6c631a9f14
  1. 11
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  2. 34
      ui-ngx/src/app/modules/home/components/profile/device/common/device-profile-common.module.ts
  3. 25
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.html
  4. 150
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-device-profile-transport-configuration.component.ts
  5. 3
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-dialog.component.html
  6. 44
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.html
  7. 104
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts
  8. 5
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.html
  9. 16
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts
  10. 4
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-components.module.ts
  11. 4
      ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-config.models.ts
  12. 22
      ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.html
  13. 38
      ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.ts
  14. 2
      ui-ngx/src/app/modules/home/pages/device/device.module.ts
  15. 26
      ui-ngx/src/app/shared/models/device.models.ts
  16. 8
      ui-ngx/src/assets/locale/locale.constant-en_US.json

11
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -141,7 +141,7 @@ import { DashboardImageDialogComponent } from '@home/components/dashboard-page/d
import { WidgetContainerComponent } from '@home/components/widget/widget-container.component'; import { WidgetContainerComponent } from '@home/components/widget/widget-container.component';
import { SnmpDeviceProfileTransportModule } from '@home/components/profile/device/snpm/snmp-device-profile-transport.module'; import { SnmpDeviceProfileTransportModule } from '@home/components/profile/device/snpm/snmp-device-profile-transport.module';
import { DeviceCredentialsModule } from '@home/components/device/device-credentials.module'; import { DeviceCredentialsModule } from '@home/components/device/device-credentials.module';
import { PowerModeSettingComponent } from '@home/components/profile/device/common/power-mode-setting.component'; import { DeviceProfileCommonModule } from '@home/components/profile/device/common/device-profile-common.module';
@NgModule({ @NgModule({
declarations: declarations:
@ -260,8 +260,7 @@ import { PowerModeSettingComponent } from '@home/components/profile/device/commo
DashboardStateDialogComponent, DashboardStateDialogComponent,
DashboardImageDialogComponent, DashboardImageDialogComponent,
EmbedDashboardDialogComponent, EmbedDashboardDialogComponent,
DisplayWidgetTypesPanelComponent, DisplayWidgetTypesPanelComponent
PowerModeSettingComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,
@ -270,7 +269,8 @@ import { PowerModeSettingComponent } from '@home/components/profile/device/commo
Lwm2mProfileComponentsModule, Lwm2mProfileComponentsModule,
SnmpDeviceProfileTransportModule, SnmpDeviceProfileTransportModule,
StatesControllerModule, StatesControllerModule,
DeviceCredentialsModule DeviceCredentialsModule,
DeviceProfileCommonModule
], ],
exports: [ exports: [
EntitiesTableComponent, EntitiesTableComponent,
@ -371,8 +371,7 @@ import { PowerModeSettingComponent } from '@home/components/profile/device/commo
DashboardStateDialogComponent, DashboardStateDialogComponent,
DashboardImageDialogComponent, DashboardImageDialogComponent,
EmbedDashboardDialogComponent, EmbedDashboardDialogComponent,
DisplayWidgetTypesPanelComponent, DisplayWidgetTypesPanelComponent
PowerModeSettingComponent
], ],
providers: [ providers: [
WidgetComponentService, WidgetComponentService,

34
ui-ngx/src/app/modules/home/components/profile/device/common/device-profile-common.module.ts

@ -0,0 +1,34 @@
///
/// 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 { NgModule } from '@angular/core';
import { PowerModeSettingComponent } from '@home/components/profile/device/common/power-mode-setting.component';
import { SharedModule } from '@shared/shared.module';
import { CommonModule } from '@angular/common';
@NgModule({
declarations: [
PowerModeSettingComponent
],
imports: [
CommonModule,
SharedModule
],
exports: [
PowerModeSettingComponent
]
})
export class DeviceProfileCommonModule { }

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

@ -132,7 +132,7 @@
<mat-option [value]=3>{{ 'device-profile.lwm2m.fw-update-strategy-data' | translate }}</mat-option> <mat-option [value]=3>{{ 'device-profile.lwm2m.fw-update-strategy-data' | translate }}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block" fxFlex *ngIf="isFwUpdateStrategy"> <mat-form-field class="mat-block" fxFlex *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateStrategy').value === 2">
<mat-label>{{ 'device-profile.lwm2m.fw-update-resource' | translate }}</mat-label> <mat-label>{{ 'device-profile.lwm2m.fw-update-resource' | translate }}</mat-label>
<input matInput formControlName="fwUpdateResource" required> <input matInput formControlName="fwUpdateResource" required>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').hasError('required')"> <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').hasError('required')">
@ -149,7 +149,7 @@
<mat-option [value]=2>{{ 'device-profile.lwm2m.sw-update-strategy-package-uri' | translate }}</mat-option> <mat-option [value]=2>{{ 'device-profile.lwm2m.sw-update-strategy-package-uri' | translate }}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<mat-form-field class="mat-block" fxFlex *ngIf="isSwUpdateStrategy"> <mat-form-field class="mat-block" fxFlex *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateStrategy').value === 2">
<mat-label>{{ 'device-profile.lwm2m.sw-update-resource' | translate }}</mat-label> <mat-label>{{ 'device-profile.lwm2m.sw-update-resource' | translate }}</mat-label>
<input matInput formControlName="swUpdateResource" required> <input matInput formControlName="swUpdateResource" required>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').hasError('required')"> <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').hasError('required')">
@ -159,25 +159,8 @@
</fieldset> </fieldset>
<fieldset class="fields-group"> <fieldset class="fields-group">
<legend class="group-title" translate>device-profile.power-saving-mode</legend> <legend class="group-title" translate>device-profile.power-saving-mode</legend>
<mat-form-field class="mat-block" fxFlex> <tb-power-mode-settings [parentForm]="clientSettingsFormGroup">
<mat-label> </mat-label> </tb-power-mode-settings>
<mat-select formControlName="powerMode">
<mat-option *ngFor="let powerMod of powerMods" [value]="powerMod">
{{ powerModeTranslationMap.get(powerMod) | translate}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="mat-block" fxFlex *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode').value === 'E_DRX'">
<mat-label>{{ 'device-profile.edrx-cycle' | translate }}</mat-label>
<input matInput type="number" min="0" formControlName="edrxCycle" required>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').hasError('required')">
{{ 'device-profile.edrx-cycle-required' | translate }}
</mat-error>
<mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').hasError('pattern') ||
lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').hasError('min')">
{{ 'device-profile.edrx-cycle-pattern' | translate }}
</mat-error>
</mat-form-field>
</fieldset> </fieldset>
<mat-slide-toggle class="mat-slider" <mat-slide-toggle class="mat-slider"
formControlName="compositeOperationsSupport">{{ 'device-profile.lwm2m.composite-operations-support' | translate }}</mat-slide-toggle> formControlName="compositeOperationsSupport">{{ 'device-profile.lwm2m.composite-operations-support' | translate }}</mat-slide-toggle>

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

@ -16,7 +16,15 @@
import { DeviceProfileTransportConfiguration } from '@shared/models/device.models'; import { DeviceProfileTransportConfiguration } from '@shared/models/device.models';
import { Component, forwardRef, Input, OnDestroy } from '@angular/core'; import { Component, forwardRef, Input, OnDestroy } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import {
ControlValueAccessor,
FormBuilder,
FormGroup, NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { import {
ATTRIBUTE, ATTRIBUTE,
@ -30,10 +38,7 @@ import {
DEFAULT_NOTIF_IF_DESIBLED, DEFAULT_NOTIF_IF_DESIBLED,
DEFAULT_SW_UPDATE_RESOURCE, DEFAULT_SW_UPDATE_RESOURCE,
getDefaultBootstrapServerSecurityConfig, getDefaultBootstrapServerSecurityConfig,
getDefaultBootstrapServersSecurityConfig,
getDefaultLwM2MServerSecurityConfig, getDefaultLwM2MServerSecurityConfig,
getDefaultProfileClientLwM2mSettingsConfig,
getDefaultProfileObserveAttrConfig,
Instance, Instance,
INSTANCES, INSTANCES,
KEY_NAME, KEY_NAME,
@ -41,7 +46,6 @@ import {
ObjectLwM2M, ObjectLwM2M,
OBSERVE, OBSERVE,
PowerMode, PowerMode,
PowerModeTranslationMap,
RESOURCES, RESOURCES,
ServerSecurityConfig, ServerSecurityConfig,
TELEMETRY TELEMETRY
@ -58,13 +62,19 @@ import { takeUntil } from 'rxjs/operators';
selector: 'tb-profile-lwm2m-device-transport-configuration', selector: 'tb-profile-lwm2m-device-transport-configuration',
templateUrl: './lwm2m-device-profile-transport-configuration.component.html', templateUrl: './lwm2m-device-profile-transport-configuration.component.html',
styleUrls: ['./lwm2m-device-profile-transport-configuration.component.scss'], styleUrls: ['./lwm2m-device-profile-transport-configuration.component.scss'],
providers: [{ providers: [
provide: NG_VALUE_ACCESSOR, {
useExisting: forwardRef(() => Lwm2mDeviceProfileTransportConfigurationComponent), provide: NG_VALUE_ACCESSOR,
multi: true useExisting: forwardRef(() => Lwm2mDeviceProfileTransportConfigurationComponent),
}] multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => Lwm2mDeviceProfileTransportConfigurationComponent),
multi: true
}]
}) })
export class Lwm2mDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, Validators, OnDestroy { export class Lwm2mDeviceProfileTransportConfigurationComponent implements ControlValueAccessor, Validator, OnDestroy {
private configurationValue: Lwm2mProfileConfigModels; private configurationValue: Lwm2mProfileConfigModels;
private requiredValue: boolean; private requiredValue: boolean;
@ -76,10 +86,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
lwm2mDeviceProfileFormGroup: FormGroup; lwm2mDeviceProfileFormGroup: FormGroup;
lwm2mDeviceConfigFormGroup: FormGroup; lwm2mDeviceConfigFormGroup: FormGroup;
sortFunction: (key: string, value: object) => object; sortFunction: (key: string, value: object) => object;
isFwUpdateStrategy: boolean;
isSwUpdateStrategy: boolean;
powerMods = Object.values(PowerMode);
powerModeTranslationMap = PowerModeTranslationMap;
get required(): boolean { get required(): boolean {
return this.requiredValue; return this.requiredValue;
@ -116,7 +122,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
fwUpdateResource: [{value: '', disabled: true}, []], fwUpdateResource: [{value: '', disabled: true}, []],
swUpdateResource: [{value: '', disabled: true}, []], swUpdateResource: [{value: '', disabled: true}, []],
powerMode: [PowerMode.DRX, Validators.required], powerMode: [PowerMode.DRX, Validators.required],
edrxCycle: [0], edrxCycle: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]],
psmActivityTimer: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]],
pagingTransmissionWindow: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]],
compositeOperationsSupport: [false] compositeOperationsSupport: [false]
}) })
}); });
@ -128,42 +136,22 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
).subscribe((fwStrategy) => { ).subscribe((fwStrategy) => {
if (fwStrategy === 2) { if (fwStrategy === 2) {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').enable({emitEvent: false}); this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').enable({emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource')
.patchValue(DEFAULT_FW_UPDATE_RESOURCE, {emitEvent: false});
this.isFwUpdateStrategy = true;
} else { } else {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').disable({emitEvent: false}); this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').disable({emitEvent: false});
this.isFwUpdateStrategy = false; this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource')
.reset(DEFAULT_FW_UPDATE_RESOURCE, {emitEvent: false});
} }
this.otaUpdateFwStrategyValidate(true);
}); });
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateStrategy').valueChanges.pipe( this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateStrategy').valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
).subscribe((swStrategy) => { ).subscribe((swStrategy) => {
if (swStrategy === 2) { if (swStrategy === 2) {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').enable({emitEvent: false}); this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').enable({emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource')
.patchValue(DEFAULT_SW_UPDATE_RESOURCE, {emitEvent: false});
this.isSwUpdateStrategy = true;
} else { } else {
this.isSwUpdateStrategy = false;
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').disable({emitEvent: false}); this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').disable({emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource')
.reset(DEFAULT_SW_UPDATE_RESOURCE, {emitEvent: false});
} }
this.otaUpdateSwStrategyValidate(true);
});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe((powerMode: PowerMode) => {
if (powerMode === PowerMode.E_DRX) {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').enable({emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').patchValue(0, {emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle')
.setValidators([Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]);
} else {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').disable({emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').clearValidators();
}
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.edrxCycle').updateValueAndValidity({emitEvent: false});
}); });
this.lwm2mDeviceProfileFormGroup.valueChanges.pipe( this.lwm2mDeviceProfileFormGroup.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
@ -198,24 +186,33 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
} else { } else {
this.lwm2mDeviceProfileFormGroup.enable({emitEvent: false}); this.lwm2mDeviceProfileFormGroup.enable({emitEvent: false});
this.lwm2mDeviceConfigFormGroup.enable({emitEvent: false}); this.lwm2mDeviceConfigFormGroup.enable({emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode').updateValueAndValidity({onlySelf: true});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateStrategy').updateValueAndValidity({onlySelf: true});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateStrategy').updateValueAndValidity({onlySelf: true});
} }
} }
async writeValue(value: Lwm2mProfileConfigModels | null) { async writeValue(value: Lwm2mProfileConfigModels | null) {
if (isDefinedAndNotNull(value)) { if (isDefinedAndNotNull(value) && (value?.clientLwM2mSettings || value?.observeAttr || value?.bootstrap)) {
if (value?.clientLwM2mSettings || value?.observeAttr || value?.bootstrap) { this.configurationValue = value;
this.configurationValue = value; const defaultFormSettings = !(value.observeAttr.attribute.length && value.observeAttr.telemetry.length);
} else {
this.configurationValue = await this.defaultProfileConfig();
}
this.lwm2mDeviceConfigFormGroup.patchValue({ this.lwm2mDeviceConfigFormGroup.patchValue({
configurationJson: this.configurationValue configurationJson: this.configurationValue
}, {emitEvent: false}); }, {emitEvent: defaultFormSettings});
if (defaultFormSettings) {
await this.defaultProfileConfig();
}
this.initWriteValue(); this.initWriteValue();
} }
} }
private async defaultProfileConfig(): Promise<Lwm2mProfileConfigModels> { validate(): ValidationErrors | null {
return this.lwm2mDeviceProfileFormGroup.valid ? null : {
lwm2mDeviceProfile: false
};
}
private async defaultProfileConfig(): Promise<void> {
let bootstrap: ServerSecurityConfig; let bootstrap: ServerSecurityConfig;
let lwm2m: ServerSecurityConfig; let lwm2m: ServerSecurityConfig;
try { try {
@ -227,15 +224,15 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
bootstrap = getDefaultBootstrapServerSecurityConfig(); bootstrap = getDefaultBootstrapServerSecurityConfig();
lwm2m = getDefaultLwM2MServerSecurityConfig(); lwm2m = getDefaultLwM2MServerSecurityConfig();
} }
return {
observeAttr: getDefaultProfileObserveAttrConfig(), this.configurationValue.bootstrap.bootstrapServer = bootstrap;
bootstrap: { this.configurationValue.bootstrap.lwm2mServer = lwm2m;
servers: getDefaultBootstrapServersSecurityConfig(), this.lwm2mDeviceConfigFormGroup.patchValue({
bootstrapServer: bootstrap, configurationJson: this.configurationValue
lwm2mServer: lwm2m }, {emitEvent: false});
}, this.lwm2mDeviceProfileFormGroup.patchValue({
clientLwM2mSettings: getDefaultProfileClientLwM2mSettingsConfig() bootstrap: this.configurationValue.bootstrap
}; }, {emitEvent: false});
} }
private initWriteValue = (): void => { private initWriteValue = (): void => {
@ -256,10 +253,6 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
} }
private updateWriteValue = (value: ObjectLwM2M[]): void => { private updateWriteValue = (value: ObjectLwM2M[]): void => {
const fwResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.fwUpdateResource) ?
this.configurationValue.clientLwM2mSettings.fwUpdateResource : '';
const swResource = isDefinedAndNotNull(this.configurationValue.clientLwM2mSettings.swUpdateResource) ?
this.configurationValue.clientLwM2mSettings.swUpdateResource : '';
this.lwm2mDeviceProfileFormGroup.patchValue({ this.lwm2mDeviceProfileFormGroup.patchValue({
objectIds: value, objectIds: value,
observeAttrTelemetry: this.getObserveAttrTelemetryObjects(value), observeAttrTelemetry: this.getObserveAttrTelemetryObjects(value),
@ -268,22 +261,19 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect, clientOnlyObserveAfterConnect: this.configurationValue.clientLwM2mSettings.clientOnlyObserveAfterConnect,
fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy || 1, fwUpdateStrategy: this.configurationValue.clientLwM2mSettings.fwUpdateStrategy || 1,
swUpdateStrategy: this.configurationValue.clientLwM2mSettings.swUpdateStrategy || 1, swUpdateStrategy: this.configurationValue.clientLwM2mSettings.swUpdateStrategy || 1,
fwUpdateResource: fwResource, fwUpdateResource: this.configurationValue.clientLwM2mSettings.fwUpdateResource || '',
swUpdateResource: swResource, swUpdateResource: this.configurationValue.clientLwM2mSettings.swUpdateResource || '',
powerMode: this.configurationValue.clientLwM2mSettings.powerMode || PowerMode.DRX, powerMode: this.configurationValue.clientLwM2mSettings.powerMode || PowerMode.DRX,
edrxCycle: this.configurationValue.clientLwM2mSettings.edrxCycle || 0, edrxCycle: this.configurationValue.clientLwM2mSettings.edrxCycle || 0,
compositeOperationsSupport: this.configurationValue.clientLwM2mSettings.compositeOperationsSupport || false compositeOperationsSupport: this.configurationValue.clientLwM2mSettings.compositeOperationsSupport || false
} }
}, },
{emitEvent: false}); {emitEvent: false});
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode') if (!this.disabled) {
.patchValue(this.configurationValue.clientLwM2mSettings.powerMode || PowerMode.DRX, {emitEvent: false, onlySelf: true}); this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.powerMode').updateValueAndValidity({onlySelf: true});
this.configurationValue.clientLwM2mSettings.fwUpdateResource = fwResource; this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateStrategy').updateValueAndValidity({onlySelf: true});
this.configurationValue.clientLwM2mSettings.swUpdateResource = swResource; this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateStrategy').updateValueAndValidity({onlySelf: true});
this.isFwUpdateStrategy = this.configurationValue.clientLwM2mSettings.fwUpdateStrategy === 2; }
this.isSwUpdateStrategy = this.configurationValue.clientLwM2mSettings.swUpdateStrategy === 2;
this.otaUpdateSwStrategyValidate();
this.otaUpdateFwStrategyValidate();
} }
private updateModel = (): void => { private updateModel = (): void => {
@ -576,22 +566,8 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
}); });
} }
private otaUpdateFwStrategyValidate(updated = false): void { get clientSettingsFormGroup(): FormGroup {
if (this.isFwUpdateStrategy) { return this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings') as FormGroup;
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').setValidators([Validators.required]);
} else {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').clearValidators();
}
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.fwUpdateResource').updateValueAndValidity({emitEvent: updated});
}
private otaUpdateSwStrategyValidate(updated = false): void {
if (this.isSwUpdateStrategy) {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').setValidators([Validators.required]);
} else {
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').clearValidators();
}
this.lwm2mDeviceProfileFormGroup.get('clientLwM2mSettings.swUpdateResource').updateValueAndValidity({emitEvent: updated});
} }
} }

3
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-dialog.component.html

@ -17,7 +17,7 @@
--> -->
<form [formGroup]="instancesFormGroup" (ngSubmit)="add()" style="min-width: 400px;"> <form [formGroup]="instancesFormGroup" (ngSubmit)="add()" style="min-width: 400px;">
<mat-toolbar fxLayout="row" color="primary"> <mat-toolbar fxLayout="row" color="primary">
<b><i>{{data.objectName}}</i></b> (object <<b>{{data.objectId}}</b>>) <span style="font-weight: 500">{{data.objectName}}</span>&nbsp;#{{data.objectId}}
<span fxFlex></span> <span fxFlex></span>
<button mat-button mat-icon-button <button mat-button mat-icon-button
(click)="cancel()" (click)="cancel()"
@ -31,6 +31,7 @@
<div mat-dialog-content> <div mat-dialog-content>
<fieldset [disabled]="isLoading$ | async"> <fieldset [disabled]="isLoading$ | async">
<tb-profile-lwm2m-object-add-instances-list <tb-profile-lwm2m-object-add-instances-list
required
formControlName="instancesIds"> formControlName="instancesIds">
</tb-profile-lwm2m-object-add-instances-list> </tb-profile-lwm2m-object-add-instances-list>
</fieldset> </fieldset>

44
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.html

@ -18,40 +18,32 @@
<section [formGroup]="instancesListFormGroup" class="lwm2m-instances-list"> <section [formGroup]="instancesListFormGroup" class="lwm2m-instances-list">
<mat-form-field class="mat-block"> <mat-form-field class="mat-block">
<mat-label>{{ 'device-profile.lwm2m.instances-list' | translate }}</mat-label> <mat-label>{{ 'device-profile.lwm2m.instances-list' | translate }}</mat-label>
<mat-chip-list> <mat-chip-list #chipList formControlName="instanceList" [required]="required" (focus)="onFocus()">
<mat-chip <mat-chip
*ngFor="let instanceId of instancesId" *ngFor="let instanceId of instancesId"
[selectable]="true" [selectable]="!disabled"
[removable]="true" [removable]="!disabled"
(removed)="remove(instanceId)"> (removed)="remove(instanceId)">
{{instanceId}} {{instanceId}}
<mat-icon matChipRemove>close</mat-icon> <mat-icon matChipRemove *ngIf="!disabled">close</mat-icon>
</mat-chip> </mat-chip>
<input matInput type="text"
#instanceId
style="max-width: 70px;"
formControlName="instanceId"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
matChipInputAddOnBlur
(matChipInputTokenEnd)="add($event)">
</mat-chip-list> </mat-chip-list>
</mat-form-field> <mat-error *ngIf="instancesListFormGroup.get('instanceList').hasError('required')">
<mat-form-field class="mat-block"> {{ 'device-profile.lwm2m.instances-list-required' | translate }}
<mat-label>{{ 'device-profile.lwm2m.instances-input' | translate }}</mat-label>
<input fxFlexFill matInput type='text'
placeholder="{{'device-profile.lwm2m.instances-input-holder' | translate}}"
formControlName="instanceIdInput">
<button mat-icon-button matSuffix
(click)="add()" type="button">
<mat-icon>add</mat-icon>
</button>
<mat-error *ngIf="instancesListFormGroup.get('instanceIdInput').hasError('min')">
{{ 'device-profile.lwm2m.valid-id-instance' | translate: {
count: 2, instance: instanceId, min: instanceIdValueMin
} }}
</mat-error> </mat-error>
<mat-error *ngIf="instancesListFormGroup.get('instanceIdInput').hasError('max')"> <mat-error *ngIf="instancesListFormGroup.get('instanceId').hasError('pattern')">
{{ 'device-profile.lwm2m.valid-id-instance' | translate: { {{ 'device-profile.lwm2m.instance-id-pattern' | translate }}
count: 1, instance: instanceId, max: instanceIdValueMax
} }}
</mat-error> </mat-error>
<mat-error *ngIf="instancesListFormGroup.get('instanceIdInput').hasError('pattern')"> <mat-error *ngIf="instancesListFormGroup.get('instanceId').hasError('max')">
{{ 'device-profile.lwm2m.valid-id-instance' | translate: { {{ 'device-profile.lwm2m.instance-id-max' | translate: {max: instanceIdValueMax} }}
count: 0, instance: instanceId, max: instanceIdValueMax
} }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</section> </section>

104
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-add-instances-list.component.ts

@ -14,37 +14,76 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, forwardRef } from '@angular/core'; import { Component, ElementRef, forwardRef, Input, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import {
import { INSTANCES_ID_VALUE_MAX, INSTANCES_ID_VALUE_MIN, KEY_REGEXP_NUMBER } from './lwm2m-profile-config.models'; ControlValueAccessor,
FormBuilder,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR, ValidationErrors, Validator,
Validators
} from '@angular/forms';
import { INSTANCES_ID_VALUE_MAX, INSTANCES_ID_VALUE_MIN } from './lwm2m-profile-config.models';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
import { MatChipInputEvent } from '@angular/material/chips';
@Component({ @Component({
selector: 'tb-profile-lwm2m-object-add-instances-list', selector: 'tb-profile-lwm2m-object-add-instances-list',
templateUrl: './lwm2m-object-add-instances-list.component.html', templateUrl: './lwm2m-object-add-instances-list.component.html',
providers: [{ providers: [
provide: NG_VALUE_ACCESSOR, {
useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent), provide: NG_VALUE_ACCESSOR,
multi: true useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent),
}] multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => Lwm2mObjectAddInstancesListComponent),
multi: true
}]
}) })
export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccessor { export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccessor, Validator {
private disabled = false; private requiredValue: boolean;
private dirty = false;
@Input()
disabled: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
this.updateValidators();
}
@ViewChild('instanceId') instanceId: ElementRef<HTMLInputElement>;
instancesListFormGroup: FormGroup; instancesListFormGroup: FormGroup;
instancesId = new Set<number>(); instancesId = new Set<number>();
instanceIdValueMin = INSTANCES_ID_VALUE_MIN; separatorKeysCodes = [ENTER, COMMA, SEMICOLON];
instanceIdValueMax = INSTANCES_ID_VALUE_MAX; instanceIdValueMax = INSTANCES_ID_VALUE_MAX;
private propagateChange = (v: any) => { }; private propagateChange = (v: any) => { };
constructor(private fb: FormBuilder) { constructor(private fb: FormBuilder) {
this.instancesListFormGroup = this.fb.group({ this.instancesListFormGroup = this.fb.group({
instanceIdInput: [null, [ instanceList: [null],
Validators.min(this.instanceIdValueMin), instanceId: [null, [
Validators.max(this.instanceIdValueMax), Validators.min(INSTANCES_ID_VALUE_MIN),
Validators.pattern(KEY_REGEXP_NUMBER)]] Validators.max(INSTANCES_ID_VALUE_MAX),
Validators.pattern('[0-9]*')]]
});
this.instancesListFormGroup.get('instanceId').statusChanges.subscribe((value) => {
if (value === 'INVALID') {
const errors = this.instancesListFormGroup.get('instanceId').errors;
this.instancesListFormGroup.get('instanceList').setErrors(errors);
} else {
this.instancesListFormGroup.get('instanceList').updateValueAndValidity({onlySelf: true});
}
}); });
} }
@ -67,26 +106,41 @@ export class Lwm2mObjectAddInstancesListComponent implements ControlValueAccesso
writeValue(value: Set<number>): void { writeValue(value: Set<number>): void {
if (value && value.size) { if (value && value.size) {
this.instancesId = value; this.instancesId = value;
this.instancesListFormGroup.patchValue({instanceList: Array.from(this.instancesId)}, {emitEvent: false});
} }
this.dirty = false;
} }
add = (): void => { validate(): ValidationErrors | null {
if (this.instancesListFormGroup.get('instanceIdInput').valid && Number.isFinite(Number(this.instanceId))) { return this.instancesListFormGroup.valid ? null : {
this.instancesId.add(Number(this.instanceId)); instancesListForm: false
this.instancesListFormGroup.get('instanceIdInput').setValue(null); };
}
add = (event: MatChipInputEvent): void => {
const value = event.value;
if (this.instancesListFormGroup.get('instanceId').valid && value !== '' && Number.isFinite(Number(value))) {
this.instancesId.add(Number(value));
this.instancesListFormGroup.patchValue({instanceList: Array.from(this.instancesId)}, {emitEvent: false});
this.instancesListFormGroup.get('instanceId').setValue(null, {emitEvent: false});
this.propagateChange(this.instancesId); this.propagateChange(this.instancesId);
this.dirty = true;
} }
} }
remove = (object: number): void => { remove = (object: number): void => {
this.instancesId.delete(object); this.instancesId.delete(object);
this.instancesListFormGroup.patchValue({instanceList: Array.from(this.instancesId)}, {emitEvent: false});
this.propagateChange(this.instancesId); this.propagateChange(this.instancesId);
this.dirty = true;
} }
get instanceId(): number { onFocus() {
return this.instancesListFormGroup.get('instanceIdInput').value; setTimeout(() => {
this.instanceId.nativeElement.blur();
this.instanceId.nativeElement.focus();
}, 0);
}
private updateValidators() {
this.instancesListFormGroup.get('instanceList').setValidators(this.required ? [Validators.required] : []);
this.instancesListFormGroup.get('instanceList').updateValueAndValidity({emitEvent: false});
} }
} }

5
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.html

@ -16,7 +16,8 @@
--> -->
<mat-form-field appearance="standard" [formGroup]="lwm2mListFormGroup" class="mat-block"> <mat-form-field appearance="standard" [formGroup]="lwm2mListFormGroup" class="mat-block">
<mat-chip-list #chipList formControlName="objectsList"> <mat-label translate>device-profile.lwm2m.object-list</mat-label>
<mat-chip-list #chipList formControlName="objectsList" [required]="required">
<mat-chip <mat-chip
*ngFor="let objectLwm2m of objectsList" *ngFor="let objectLwm2m of objectsList"
[selectable]="!disabled" [selectable]="!disabled"
@ -25,7 +26,7 @@
{{objectLwm2m.name}} #{{objectLwm2m.keyId}} {{objectLwm2m.name}} #{{objectLwm2m.keyId}}
<mat-icon matChipRemove *ngIf="!disabled">close</mat-icon> <mat-icon matChipRemove *ngIf="!disabled">close</mat-icon>
</mat-chip> </mat-chip>
<input matInput type="text" placeholder="{{ !disabled ? ('device-profile.lwm2m.object-list' | translate) : '' }}" <input matInput type="text"
style="max-width: 200px;" style="max-width: 200px;"
#objectInput #objectInput
(focusin)="onFocus()" (focusin)="onFocus()"

16
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-object-list.component.ts

@ -131,7 +131,7 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
if (isDisabled) { if (isDisabled) {
this.lwm2mListFormGroup.disable({emitEvent: false}); this.lwm2mListFormGroup.disable({emitEvent: false});
if (isDefined(this.objectInput)) { if (isDefined(this.objectInput)) {
this.clear(); this.clear('', false);
} }
} else { } else {
this.lwm2mListFormGroup.enable({emitEvent: false}); this.lwm2mListFormGroup.enable({emitEvent: false});
@ -196,12 +196,14 @@ export class Lwm2mObjectListComponent implements ControlValueAccessor, OnInit, V
} }
} }
private clear(value: string = '') { private clear(value = '', emitEvent = true) {
this.objectInput.nativeElement.value = value; this.objectInput.nativeElement.value = value;
this.lwm2mListFormGroup.get('objectLwm2m').patchValue(value); this.lwm2mListFormGroup.get('objectLwm2m').patchValue(value, {emitEvent});
setTimeout(() => { if (emitEvent) {
this.objectInput.nativeElement.blur(); setTimeout(() => {
this.objectInput.nativeElement.focus(); this.objectInput.nativeElement.blur();
}, 0); this.objectInput.nativeElement.focus();
}, 0);
}
} }
} }

4
ui-ngx/src/app/modules/home/components/profile/device/lwm2m/lwm2m-profile-components.module.ts

@ -28,6 +28,7 @@ import { Lwm2mObjectAddInstancesListComponent } from './lwm2m-object-add-instanc
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { SharedModule } from '@app/shared/shared.module'; import { SharedModule } from '@app/shared/shared.module';
import { Lwm2mObserveAttrTelemetryInstancesComponent } from './lwm2m-observe-attr-telemetry-instances.component'; import { Lwm2mObserveAttrTelemetryInstancesComponent } from './lwm2m-observe-attr-telemetry-instances.component';
import { DeviceProfileCommonModule } from '@home/components/profile/device/common/device-profile-common.module';
@NgModule({ @NgModule({
declarations: declarations:
@ -46,7 +47,8 @@ import { Lwm2mObserveAttrTelemetryInstancesComponent } from './lwm2m-observe-att
], ],
imports: [ imports: [
CommonModule, CommonModule,
SharedModule SharedModule,
DeviceProfileCommonModule
], ],
exports: [ exports: [
Lwm2mDeviceProfileTransportConfigurationComponent, Lwm2mDeviceProfileTransportConfigurationComponent,

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

@ -18,7 +18,6 @@ import { ValidatorFn, Validators } from '@angular/forms';
export const PAGE_SIZE_LIMIT = 50; export const PAGE_SIZE_LIMIT = 50;
export const INSTANCES = 'instances'; export const INSTANCES = 'instances';
export const INSTANCE = 'instance';
export const RESOURCES = 'resources'; export const RESOURCES = 'resources';
export const OBSERVE = 'observe'; export const OBSERVE = 'observe';
export const ATTRIBUTE = 'attribute'; export const ATTRIBUTE = 'attribute';
@ -38,7 +37,6 @@ export const DEFAULT_BOOTSTRAP_SERVER_ACCOUNT_TIME_OUT = 0;
export const LEN_MAX_PUBLIC_KEY_RPK = 182; export const LEN_MAX_PUBLIC_KEY_RPK = 182;
export const LEN_MAX_PUBLIC_KEY_X509 = 3000; export const LEN_MAX_PUBLIC_KEY_X509 = 3000;
export const KEY_REGEXP_HEX_DEC = /^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$/; export const KEY_REGEXP_HEX_DEC = /^[-+]?[0-9A-Fa-f]+\.?[0-9A-Fa-f]*?$/;
export const KEY_REGEXP_NUMBER = /^(-?|\+?)\d*$/;
export const INSTANCES_ID_VALUE_MIN = 0; export const INSTANCES_ID_VALUE_MIN = 0;
export const INSTANCES_ID_VALUE_MAX = 65535; export const INSTANCES_ID_VALUE_MAX = 65535;
export const DEFAULT_OTA_UPDATE_PROTOCOL = 'coap://'; export const DEFAULT_OTA_UPDATE_PROTOCOL = 'coap://';
@ -170,6 +168,8 @@ export interface ClientLwM2mSettings {
swUpdateResource: string; swUpdateResource: string;
powerMode: PowerMode; powerMode: PowerMode;
edrxCycle?: number; edrxCycle?: number;
pagingTransmissionWindow?: number;
psmActivityTimer?: number;
compositeOperationsSupport: boolean; compositeOperationsSupport: boolean;
} }

22
ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.html

@ -16,24 +16,6 @@
--> -->
<form [formGroup]="lwm2mDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;"> <form [formGroup]="lwm2mDeviceTransportConfigurationFormGroup" style="padding-bottom: 16px;">
<mat-form-field class="mat-block" fxFlex> <tb-power-mode-settings [parentForm]="lwm2mDeviceTransportConfigurationFormGroup" [isDeviceSetting]="true">
<mat-label translate>device-profile.power-saving-mode</mat-label> </tb-power-mode-settings>
<mat-select formControlName="powerMode">
<mat-option [value]="null">{{ "device-profile.power-saving-mode-type.default" | translate }}</mat-option>
<mat-option *ngFor="let powerMod of powerMods" [value]="powerMod">
{{ powerModeTranslationMap.get(powerMod) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="mat-block" fxFlex *ngIf="lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').value === 'E_DRX'">
<mat-label>{{ 'device-profile.edrx-cycle' | translate }}</mat-label>
<input matInput type="number" min="0" formControlName="edrxCycle" required>
<mat-error *ngIf="lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').hasError('required')">
{{ 'device-profile.edrx-cycle-required' | translate }}
</mat-error>
<mat-error *ngIf="lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').hasError('pattern') ||
lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').hasError('min')">
{{ 'device-profile.edrx-cycle-pattern' | translate }}
</mat-error>
</mat-form-field>
</form> </form>

38
ui-ngx/src/app/modules/home/pages/device/data/lwm2m-device-transport-configuration.component.ts

@ -19,8 +19,11 @@ import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Valida
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@app/core/core.state'; import { AppState } from '@app/core/core.state';
import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { DeviceTransportConfiguration, Lwm2mDeviceTransportConfiguration } from '@shared/models/device.models'; import {
import { PowerMode, PowerModeTranslationMap } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; DeviceTransportConfiguration,
DeviceTransportType,
Lwm2mDeviceTransportConfiguration
} from '@shared/models/device.models';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
import { isDefinedAndNotNull } from '@core/utils'; import { isDefinedAndNotNull } from '@core/utils';
@ -38,8 +41,6 @@ import { isDefinedAndNotNull } from '@core/utils';
export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy { export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueAccessor, OnInit, OnDestroy {
lwm2mDeviceTransportConfigurationFormGroup: FormGroup; lwm2mDeviceTransportConfigurationFormGroup: FormGroup;
powerMods = Object.values(PowerMode);
powerModeTranslationMap = PowerModeTranslationMap;
private requiredValue: boolean; private requiredValue: boolean;
get required(): boolean { get required(): boolean {
@ -70,21 +71,9 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
ngOnInit() { ngOnInit() {
this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({ this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({
powerMode: [null], powerMode: [null],
edrxCycle: [0] edrxCycle: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]],
}); psmActivityTimer: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]],
this.lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').valueChanges.pipe( pagingTransmissionWindow: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]]
takeUntil(this.destroy$)
).subscribe((powerMode: PowerMode) => {
if (powerMode === PowerMode.E_DRX) {
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').enable({emitEvent: false});
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').patchValue(0, {emitEvent: false});
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle')
.setValidators([Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]);
} else {
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').disable({emitEvent: false});
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').clearValidators();
}
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').updateValueAndValidity({emitEvent: false});
}); });
this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.pipe( this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)
@ -104,15 +93,18 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
this.lwm2mDeviceTransportConfigurationFormGroup.disable({emitEvent: false}); this.lwm2mDeviceTransportConfigurationFormGroup.disable({emitEvent: false});
} else { } else {
this.lwm2mDeviceTransportConfigurationFormGroup.enable({emitEvent: false}); this.lwm2mDeviceTransportConfigurationFormGroup.enable({emitEvent: false});
this.lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').updateValueAndValidity({onlySelf: true});
} }
} }
writeValue(value: Lwm2mDeviceTransportConfiguration | null): void { writeValue(value: Lwm2mDeviceTransportConfiguration | null): void {
if (isDefinedAndNotNull(value)) { if (isDefinedAndNotNull(value)) {
this.lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').patchValue(value.powerMode, {emitEvent: false, onlySelf: true}); this.lwm2mDeviceTransportConfigurationFormGroup.patchValue(value, {emitEvent: false});
this.lwm2mDeviceTransportConfigurationFormGroup.get('edrxCycle').patchValue(value.edrxCycle || 0, {emitEvent: false});
} else { } else {
this.lwm2mDeviceTransportConfigurationFormGroup.patchValue({powerMode: null, edrxCycle: 0}, {emitEvent: false}); this.lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').patchValue(null, {emitEvent: false});
}
if (!this.disabled) {
this.lwm2mDeviceTransportConfigurationFormGroup.get('powerMode').updateValueAndValidity({onlySelf: true});
} }
} }
@ -120,7 +112,7 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
let configuration: DeviceTransportConfiguration = null; let configuration: DeviceTransportConfiguration = null;
if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) { if (this.lwm2mDeviceTransportConfigurationFormGroup.valid) {
configuration = this.lwm2mDeviceTransportConfigurationFormGroup.value; configuration = this.lwm2mDeviceTransportConfigurationFormGroup.value;
// configuration.type = DeviceTransportType.LWM2M; configuration.type = DeviceTransportType.LWM2M;
} }
this.propagateChange(configuration); this.propagateChange(configuration);
} }

2
ui-ngx/src/app/modules/home/pages/device/device.module.ts

@ -34,6 +34,7 @@ import { CoapDeviceTransportConfigurationComponent } from './data/coap-device-tr
import { Lwm2mDeviceTransportConfigurationComponent } from './data/lwm2m-device-transport-configuration.component'; import { Lwm2mDeviceTransportConfigurationComponent } from './data/lwm2m-device-transport-configuration.component';
import { SnmpDeviceTransportConfigurationComponent } from './data/snmp-device-transport-configuration.component'; import { SnmpDeviceTransportConfigurationComponent } from './data/snmp-device-transport-configuration.component';
import { DeviceCredentialsModule } from '@home/components/device/device-credentials.module'; import { DeviceCredentialsModule } from '@home/components/device/device-credentials.module';
import { DeviceProfileCommonModule } from '@home/components/profile/device/common/device-profile-common.module';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -57,6 +58,7 @@ import { DeviceCredentialsModule } from '@home/components/device/device-credenti
HomeComponentsModule, HomeComponentsModule,
HomeDialogsModule, HomeDialogsModule,
DeviceCredentialsModule, DeviceCredentialsModule,
DeviceProfileCommonModule,
DeviceRoutingModule DeviceRoutingModule
] ]
}) })

26
ui-ngx/src/app/shared/models/device.models.ts

@ -30,7 +30,14 @@ import { AbstractControl, ValidationErrors } from '@angular/forms';
import { OtaPackageId } from '@shared/models/id/ota-package-id'; 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 { PowerMode } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; import {
getDefaultBootstrapServerSecurityConfig,
getDefaultBootstrapServersSecurityConfig,
getDefaultLwM2MServerSecurityConfig,
getDefaultProfileClientLwM2mSettingsConfig,
getDefaultProfileObserveAttrConfig,
PowerMode
} from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
export enum DeviceProfileType { export enum DeviceProfileType {
DEFAULT = 'DEFAULT', DEFAULT = 'DEFAULT',
@ -369,7 +376,15 @@ export function createDeviceProfileTransportConfiguration(type: DeviceTransportT
transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP}; transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP};
break; break;
case DeviceTransportType.LWM2M: case DeviceTransportType.LWM2M:
const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = {}; const lwm2mTransportConfiguration: Lwm2mDeviceProfileTransportConfiguration = {
observeAttr: getDefaultProfileObserveAttrConfig(),
bootstrap: {
servers: getDefaultBootstrapServersSecurityConfig(),
bootstrapServer: getDefaultBootstrapServerSecurityConfig(),
lwm2mServer: getDefaultLwM2MServerSecurityConfig()
},
clientLwM2mSettings: getDefaultProfileClientLwM2mSettingsConfig()
};
transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M};
break; break;
case DeviceTransportType.SNMP: case DeviceTransportType.SNMP:
@ -404,7 +419,9 @@ export function createDeviceTransportConfiguration(type: DeviceTransportType): D
transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP}; transportConfiguration = {...coapTransportConfiguration, type: DeviceTransportType.COAP};
break; break;
case DeviceTransportType.LWM2M: case DeviceTransportType.LWM2M:
const lwm2mTransportConfiguration: Lwm2mDeviceTransportConfiguration = {}; const lwm2mTransportConfiguration: Lwm2mDeviceTransportConfiguration = {
powerMode: null
};
transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M}; transportConfiguration = {...lwm2mTransportConfiguration, type: DeviceTransportType.LWM2M};
break; break;
case DeviceTransportType.SNMP: case DeviceTransportType.SNMP:
@ -592,7 +609,8 @@ export interface CoapDeviceTransportConfiguration {
export interface Lwm2mDeviceTransportConfiguration { export interface Lwm2mDeviceTransportConfiguration {
powerMode?: PowerMode | null; powerMode?: PowerMode | null;
edrxCycle?: number; edrxCycle?: number;
[key: string]: any; pagingTransmissionWindow?: number;
psmActivityTimer?: number;
} }
export enum SnmpDeviceProtocolVersion { export enum SnmpDeviceProtocolVersion {

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

@ -1242,14 +1242,12 @@
"object-list": "Object list", "object-list": "Object list",
"object-list-empty": "No objects selected.", "object-list-empty": "No objects selected.",
"no-objects-matching": "No objects matching '{{object}}' were found.", "no-objects-matching": "No objects matching '{{object}}' were found.",
"valid-id-instance-no-min": "Instance number '{{instance}}' no validated. Min value='{{min}}'",
"valid-id-instance-no-max": "Instance number '{{instance}}' no validated. Max value='{{max}}'",
"valid-id-instance": "Instance number '{{instance}}' no validated. { count, plural, 1 {Max value='{{max}}'} 2 {Min value='{{min}}'} other {Must be only number} }",
"model-tab": "LWM2M Model", "model-tab": "LWM2M Model",
"add-new-instances": "Add new instances", "add-new-instances": "Add new instances",
"instances-list": "Instances list", "instances-list": "Instances list",
"instances-input": "Input Instance Id value", "instances-list-required": "Instances list is required.",
"instances-input-holder": "Input Instance number...", "instance-id-pattern": "Instance id must be a positive integer.",
"instance-id-max": "Maximum instance id value {{max}}.",
"instance": "Instance", "instance": "Instance",
"resource-label": "#ID Resource name", "resource-label": "#ID Resource name",
"observe-label": "Observe", "observe-label": "Observe",

Loading…
Cancel
Save