UI: Add select time unit for power mode in CoAP and LwM2M profile

This commit is contained in:
Vladyslav_Prykhodko 2021-07-30 14:40:47 +03:00 committed by Vladyslav
parent d4dc0ad1cf
commit e4bfbacdd8
13 changed files with 309 additions and 61 deletions

View File

@ -101,9 +101,9 @@ export class CoapDeviceProfileTransportConfigurationComponent implements Control
}), }),
clientSettings: this.fb.group({ clientSettings: this.fb.group({
powerMode: [PowerMode.DRX, Validators.required], powerMode: [PowerMode.DRX, Validators.required],
edrxCycle: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], edrxCycle: [{disabled: true, value: 0}, Validators.required],
psmActivityTimer: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], psmActivityTimer: [{disabled: true, value: 0}, Validators.required],
pagingTransmissionWindow: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]] pagingTransmissionWindow: [{disabled: true, value: 0}, Validators.required]
})} })}
); );
this.coapTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType').valueChanges.pipe( this.coapTransportConfigurationFormGroup.get('coapDeviceTypeConfiguration.coapDeviceType').valueChanges.pipe(

View File

@ -15,13 +15,15 @@
/// ///
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { PowerModeSettingComponent } from '@home/components/profile/device/common/power-mode-setting.component'; import { PowerModeSettingComponent } from './power-mode-setting.component';
import { SharedModule } from '@shared/shared.module'; import { SharedModule } from '@shared/shared.module';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { TimeUnitSelectComponent } from './time-unit-select.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
PowerModeSettingComponent PowerModeSettingComponent,
TimeUnitSelectComponent
], ],
imports: [ imports: [
CommonModule, CommonModule,

View File

@ -26,38 +26,27 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<section class="mat-block" fxFlex *ngIf="parentForm.get('powerMode').value === 'E_DRX'"> <section class="mat-block" fxFlex *ngIf="parentForm.get('powerMode').value === 'E_DRX'">
<mat-form-field class="mat-block" fxFlex> <tb-time-unit-select [labelText]="'device-profile.edrx-cycle'"
<mat-label>{{ 'device-profile.edrx-cycle' | translate }}</mat-label> [requiredText]="'device-profile.edrx-cycle-required'"
<input matInput type="number" min="0" formControlName="edrxCycle" required> [patternText]="'device-profile.edrx-cycle-pattern'"
<mat-error *ngIf="parentForm.get('edrxCycle').hasError('required')"> [minTime]="20480"
{{ 'device-profile.edrx-cycle-required' | translate }} [minText]="'device-profile.edrx-cycle-min'"
</mat-error> formControlName="edrxCycle">
<mat-error *ngIf="parentForm.get('edrxCycle').hasError('pattern') || </tb-time-unit-select>
parentForm.get('edrxCycle').hasError('min')"> <tb-time-unit-select [labelText]="'device-profile.paging-transmission-window'"
{{ 'device-profile.edrx-cycle-pattern' | translate }} [requiredText]="'device-profile.paging-transmission-window-required'"
</mat-error> [patternText]="'device-profile.paging-transmission-window-pattern'"
</mat-form-field> [minTime]="2000"
<mat-form-field class="mat-block" fxFlex> [minText]="'device-profile.paging-transmission-window-min'"
<mat-label>{{ 'device-profile.paging-transmission-window' | translate }}</mat-label> formControlName="pagingTransmissionWindow">
<input matInput type="number" min="0" formControlName="pagingTransmissionWindow" required> </tb-time-unit-select>
<mat-error *ngIf="parentForm.get('pagingTransmissionWindow').hasError('required')">
{{ 'device-profile.paging-transmission-window-required' | translate }}
</mat-error>
<mat-error *ngIf="parentForm.get('pagingTransmissionWindow').hasError('pattern') ||
parentForm.get('pagingTransmissionWindow').hasError('min')">
{{ 'device-profile.paging-transmission-window-pattern' | translate }}
</mat-error>
</mat-form-field>
</section> </section>
<mat-form-field class="mat-block" fxFlex *ngIf="parentForm.get('powerMode').value === 'PSM'"> <tb-time-unit-select *ngIf="parentForm.get('powerMode').value === 'PSM'"
<mat-label>{{ 'device-profile.psm-activity-timer' | translate }}</mat-label> [labelText]="'device-profile.psm-activity-timer'"
<input matInput type="number" min="0" formControlName="psmActivityTimer" required> [requiredText]="'device-profile.psm-activity-timer-required'"
<mat-error *ngIf="parentForm.get('psmActivityTimer').hasError('required')"> [patternText]="'device-profile.psm-activity-timer-pattern'"
{{ 'device-profile.psm-activity-timer-required' | translate }} [minTime]="2000"
</mat-error> [minText]="'device-profile.psm-activity-timer-min'"
<mat-error *ngIf="parentForm.get('psmActivityTimer').hasError('pattern') || formControlName="psmActivityTimer">
parentForm.get('psmActivityTimer').hasError('min')"> </tb-time-unit-select>
{{ 'device-profile.psm-activity-timer-pattern' | translate }}
</mat-error>
</mat-form-field>
</section> </section>

View File

@ -16,7 +16,12 @@
import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { Component, Input, OnDestroy, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms'; import { FormGroup } from '@angular/forms';
import { PowerMode, PowerModeTranslationMap } from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models'; import {
DEFAULT_EDRX_CYCLE,
DEFAULT_PAGING_TRANSMISSION_WINDOW, DEFAULT_PSM_ACTIVITY_TIMER,
PowerMode,
PowerModeTranslationMap
} from '@home/components/profile/device/lwm2m/lwm2m-profile-config.models';
import { takeUntil } from 'rxjs/operators'; import { takeUntil } from 'rxjs/operators';
import { Subject } from 'rxjs'; import { Subject } from 'rxjs';
@ -63,13 +68,13 @@ export class PowerModeSettingComponent implements OnInit, OnDestroy {
private disablePSKMode() { private disablePSKMode() {
this.parentForm.get('psmActivityTimer').disable({emitEvent: false}); this.parentForm.get('psmActivityTimer').disable({emitEvent: false});
this.parentForm.get('psmActivityTimer').reset(0, {emitEvent: false}); this.parentForm.get('psmActivityTimer').reset(DEFAULT_PSM_ACTIVITY_TIMER, {emitEvent: false});
} }
private disableEdrxMode() { private disableEdrxMode() {
this.parentForm.get('edrxCycle').disable({emitEvent: false}); this.parentForm.get('edrxCycle').disable({emitEvent: false});
this.parentForm.get('edrxCycle').reset(0, {emitEvent: false}); this.parentForm.get('edrxCycle').reset(DEFAULT_EDRX_CYCLE, {emitEvent: false});
this.parentForm.get('pagingTransmissionWindow').disable({emitEvent: false}); this.parentForm.get('pagingTransmissionWindow').disable({emitEvent: false});
this.parentForm.get('pagingTransmissionWindow').reset(0, {emitEvent: false}); this.parentForm.get('pagingTransmissionWindow').reset(DEFAULT_PAGING_TRANSMISSION_WINDOW, {emitEvent: false});
} }
} }

View File

@ -0,0 +1,40 @@
<!--
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.
-->
<section [formGroup]="timeUnitSelectFormGroup" fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
<mat-form-field class="mat-block" fxFlex>
<mat-label>{{ labelText | translate }}</mat-label>
<input matInput type="number" min="0" formControlName="time" required>
<mat-error *ngIf="timeUnitSelectFormGroup.get('time').hasError('required')">
{{ requiredText | translate }}
</mat-error>
<mat-error *ngIf="timeUnitSelectFormGroup.get('time').hasError('pattern')">
{{ patternText | translate }}
</mat-error>
<mat-error *ngIf="timeUnitSelectFormGroup.get('time').hasError('min')">
{{ (minText || patternText) | translate : {min: minTime/1000} }}
</mat-error>
</mat-form-field>
<mat-form-field class="mat-block" fxFlex>
<mat-label translate>device-profile.condition-duration-time-unit</mat-label>
<mat-select formControlName="unit">
<mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">
{{ timeUnitTranslations.get(timeUnit) | translate }}
</mat-option>
</mat-select>
</mat-form-field>
</section>

View File

@ -0,0 +1,194 @@
///
/// 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, OnDestroy, OnInit } from '@angular/core';
import {
ControlValueAccessor,
FormBuilder,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import {
FullTimeUnit,
HOUR,
MINUTE,
SECOND,
TimeUnit,
TimeUnitMilli,
timeUnitTranslationMap
} from '@shared/models/time/time.models';
import { isDefinedAndNotNull, isNumber } from '@core/utils';
interface FormGroupModel {
time: number;
unit: FullTimeUnit;
}
@Component({
selector: 'tb-time-unit-select',
templateUrl: './time-unit-select.component.html',
styleUrls: [],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TimeUnitSelectComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => TimeUnitSelectComponent),
multi: true
}
]
})
export class TimeUnitSelectComponent implements OnInit, OnDestroy, ControlValueAccessor, Validator {
timeUnitSelectFormGroup: FormGroup;
timeUnits = Object.values({...TimeUnitMilli, ...TimeUnit}).filter(item => item !== TimeUnit.DAYS);
timeUnitTranslations = timeUnitTranslationMap;
private destroy$ = new Subject();
private timeUnitToTimeMap = new Map<FullTimeUnit, number>(
[
[TimeUnitMilli.MILLISECONDS, 1],
[TimeUnit.SECONDS, SECOND],
[TimeUnit.MINUTES, MINUTE],
[TimeUnit.HOURS, HOUR]
]
);
private timeToTimeUnitMap = new Map<number, FullTimeUnit>(
[
[SECOND, TimeUnitMilli.MILLISECONDS],
[MINUTE, TimeUnit.SECONDS],
[HOUR, TimeUnit.MINUTES]
]
);
@Input()
disabled: boolean;
@Input()
labelText: string;
@Input()
requiredText: string;
@Input()
patternText: string;
@Input()
minTime = 0;
@Input()
minText: string;
private propagateChange = (v: any) => {
}
constructor(private fb: FormBuilder) {
}
ngOnInit() {
this.timeUnitSelectFormGroup = this.fb.group({
time: [0, [Validators.required, Validators.min(this.minTime), Validators.pattern('[0-9]*')]],
unit: [TimeUnitMilli.MILLISECONDS]
});
this.timeUnitSelectFormGroup.valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe((value) => {
this.updateModel(value);
});
this.timeUnitSelectFormGroup.get('unit').valueChanges.pipe(
takeUntil(this.destroy$)
).subscribe((unit: FullTimeUnit) => {
if (this.minTime > 0) {
const unitTime = this.timeUnitToTimeMap.get(unit);
const validationTime = Math.ceil(this.minTime / unitTime);
this.timeUnitSelectFormGroup.get('time').setValidators([Validators.required, Validators.min(validationTime), Validators.pattern('[0-9]*')]);
this.timeUnitSelectFormGroup.get('time').updateValueAndValidity({emitEvent: false});
}
});
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
registerOnChange(fn: any) {
this.propagateChange = fn;
}
registerOnTouched(fn: any) {
}
setDisabledState(isDisabled: boolean) {
this.disabled = isDisabled;
if (this.disabled) {
this.timeUnitSelectFormGroup.disable({emitEvent: false});
} else {
this.timeUnitSelectFormGroup.enable({emitEvent: false});
}
}
writeValue(value: number) {
const formValue: FormGroupModel = {
time: 0,
unit: TimeUnitMilli.MILLISECONDS
};
if (isDefinedAndNotNull(value) && isNumber(value) && value >= 0) {
formValue.unit = this.calculateTimeUnit(value);
formValue.time = value / this.timeUnitToTimeMap.get(formValue.unit);
}
this.timeUnitSelectFormGroup.reset(formValue, {emitEvent: false});
this.timeUnitSelectFormGroup.get('unit').updateValueAndValidity({onlySelf: true});
}
validate(): ValidationErrors | null {
return this.timeUnitSelectFormGroup.valid ? null : {
timeUnitSelect: false
};
}
private updateModel(value: FormGroupModel) {
const time = value.time * this.timeUnitToTimeMap.get(value.unit);
this.propagateChange(time);
}
private calculateTimeUnit(value: number): FullTimeUnit {
if (value === 0) {
return TimeUnitMilli.MILLISECONDS;
}
const iterators = this.timeToTimeUnitMap[Symbol.iterator]();
let iterator = iterators.next();
while (!iterator.done) {
if (!Number.isInteger(value / iterator.value[0])) {
return iterator.value[1];
}
iterator = iterators.next();
}
return TimeUnit.HOURS;
}
}

View File

@ -18,7 +18,8 @@ import { Component, forwardRef, Input, OnDestroy } from '@angular/core';
import { import {
ControlValueAccessor, ControlValueAccessor,
FormBuilder, FormBuilder,
FormGroup, NG_VALIDATORS, FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
ValidationErrors, ValidationErrors,
Validator, Validator,
@ -30,11 +31,14 @@ import {
BingingMode, BingingMode,
BingingModeTranslationsMap, BingingModeTranslationsMap,
DEFAULT_BINDING, DEFAULT_BINDING,
DEFAULT_EDRX_CYCLE,
DEFAULT_FW_UPDATE_RESOURCE, DEFAULT_FW_UPDATE_RESOURCE,
DEFAULT_ID_SERVER, DEFAULT_ID_SERVER,
DEFAULT_LIFE_TIME, DEFAULT_LIFE_TIME,
DEFAULT_MIN_PERIOD, DEFAULT_MIN_PERIOD,
DEFAULT_NOTIF_IF_DESIBLED, DEFAULT_NOTIF_IF_DESIBLED,
DEFAULT_PAGING_TRANSMISSION_WINDOW,
DEFAULT_PSM_ACTIVITY_TIMER,
DEFAULT_SW_UPDATE_RESOURCE, DEFAULT_SW_UPDATE_RESOURCE,
getDefaultBootstrapServerSecurityConfig, getDefaultBootstrapServerSecurityConfig,
getDefaultLwM2MServerSecurityConfig, getDefaultLwM2MServerSecurityConfig,
@ -120,9 +124,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: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], edrxCycle: [{disabled: true, value: 0}, Validators.required],
psmActivityTimer: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], psmActivityTimer: [{disabled: true, value: 0}, Validators.required],
pagingTransmissionWindow: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], pagingTransmissionWindow: [{disabled: true, value: 0}, Validators.required],
compositeOperationsSupport: [false] compositeOperationsSupport: [false]
}) })
}); });
@ -247,9 +251,10 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro
fwUpdateResource: this.configurationValue.clientLwM2mSettings.fwUpdateResource || '', fwUpdateResource: this.configurationValue.clientLwM2mSettings.fwUpdateResource || '',
swUpdateResource: this.configurationValue.clientLwM2mSettings.swUpdateResource || '', 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 || DEFAULT_EDRX_CYCLE,
pagingTransmissionWindow: this.configurationValue.clientLwM2mSettings.pagingTransmissionWindow || 0, pagingTransmissionWindow:
psmActivityTimer: this.configurationValue.clientLwM2mSettings.psmActivityTimer || 0, this.configurationValue.clientLwM2mSettings.pagingTransmissionWindow || DEFAULT_PAGING_TRANSMISSION_WINDOW,
psmActivityTimer: this.configurationValue.clientLwM2mSettings.psmActivityTimer || DEFAULT_PSM_ACTIVITY_TIMER,
compositeOperationsSupport: this.configurationValue.clientLwM2mSettings.compositeOperationsSupport || false compositeOperationsSupport: this.configurationValue.clientLwM2mSettings.compositeOperationsSupport || false
} }
}, },

View File

@ -42,7 +42,9 @@ export const INSTANCES_ID_VALUE_MAX = 65535;
export const DEFAULT_OTA_UPDATE_PROTOCOL = 'coap://'; export const DEFAULT_OTA_UPDATE_PROTOCOL = 'coap://';
export const DEFAULT_FW_UPDATE_RESOURCE = DEFAULT_OTA_UPDATE_PROTOCOL + DEFAULT_LOCAL_HOST_NAME + ':' + DEFAULT_PORT_SERVER_NO_SEC; export const DEFAULT_FW_UPDATE_RESOURCE = DEFAULT_OTA_UPDATE_PROTOCOL + DEFAULT_LOCAL_HOST_NAME + ':' + DEFAULT_PORT_SERVER_NO_SEC;
export const DEFAULT_SW_UPDATE_RESOURCE = DEFAULT_OTA_UPDATE_PROTOCOL + DEFAULT_LOCAL_HOST_NAME + ':' + DEFAULT_PORT_SERVER_NO_SEC; export const DEFAULT_SW_UPDATE_RESOURCE = DEFAULT_OTA_UPDATE_PROTOCOL + DEFAULT_LOCAL_HOST_NAME + ':' + DEFAULT_PORT_SERVER_NO_SEC;
export const DEFAULT_PSM_ACTIVITY_TIMER = 10000;
export const DEFAULT_EDRX_CYCLE = 81000;
export const DEFAULT_PAGING_TRANSMISSION_WINDOW = 10000;
export enum BingingMode { export enum BingingMode {
U = 'U', U = 'U',

View File

@ -71,9 +71,9 @@ export class CoapDeviceTransportConfigurationComponent implements ControlValueAc
ngOnInit() { ngOnInit() {
this.coapDeviceTransportForm = this.fb.group({ this.coapDeviceTransportForm = this.fb.group({
powerMode: [null], powerMode: [null],
edrxCycle: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], edrxCycle: [{disabled: true, value: 0}, Validators.required],
psmActivityTimer: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], psmActivityTimer: [{disabled: true, value: 0}, Validators.required],
pagingTransmissionWindow: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]] pagingTransmissionWindow: [{disabled: true, value: 0}, Validators.required]
}); });
this.coapDeviceTransportForm.valueChanges.pipe( this.coapDeviceTransportForm.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)

View File

@ -71,9 +71,9 @@ export class Lwm2mDeviceTransportConfigurationComponent implements ControlValueA
ngOnInit() { ngOnInit() {
this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({ this.lwm2mDeviceTransportConfigurationFormGroup = this.fb.group({
powerMode: [null], powerMode: [null],
edrxCycle: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], edrxCycle: [{disabled: true, value: 0}, Validators.required],
psmActivityTimer: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]], psmActivityTimer: [{disabled: true, value: 0}, Validators.required],
pagingTransmissionWindow: [{disabled: true, value: 0}, [Validators.required, Validators.min(0), Validators.pattern('[0-9]*')]] pagingTransmissionWindow: [{disabled: true, value: 0}, Validators.required]
}); });
this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.pipe( this.lwm2mDeviceTransportConfigurationFormGroup.valueChanges.pipe(
takeUntil(this.destroy$) takeUntil(this.destroy$)

View File

@ -812,8 +812,15 @@ export enum TimeUnit {
DAYS = 'DAYS' DAYS = 'DAYS'
} }
export const timeUnitTranslationMap = new Map<TimeUnit, string>( export enum TimeUnitMilli {
MILLISECONDS = 'MILLISECONDS'
}
export type FullTimeUnit = TimeUnit | TimeUnitMilli;
export const timeUnitTranslationMap = new Map<FullTimeUnit, string>(
[ [
[TimeUnitMilli.MILLISECONDS, 'timeunit.milliseconds'],
[TimeUnit.SECONDS, 'timeunit.seconds'], [TimeUnit.SECONDS, 'timeunit.seconds'],
[TimeUnit.MINUTES, 'timeunit.minutes'], [TimeUnit.MINUTES, 'timeunit.minutes'],
[TimeUnit.HOURS, 'timeunit.hours'], [TimeUnit.HOURS, 'timeunit.hours'],

View File

@ -1229,7 +1229,7 @@
"drx": "Přerušovaný přenos (DRX)", "drx": "Přerušovaný přenos (DRX)",
"edrx": "Rozšířený přerušovaný přenos (eDRX)" "edrx": "Rozšířený přerušovaný přenos (eDRX)"
}, },
"edrx-cycle": "eDRX cyklus v milisekudnách", "edrx-cycle": "eDRX cyklus",
"edrx-cycle-required": "eDRX cyklus je povinný.", "edrx-cycle-required": "eDRX cyklus je povinný.",
"edrx-cycle-pattern": "eDRX cyklus musí být kladné číslo.", "edrx-cycle-pattern": "eDRX cyklus musí být kladné číslo.",
"lwm2m": { "lwm2m": {

View File

@ -1232,15 +1232,18 @@
"drx": "Discontinuous Reception (DRX)", "drx": "Discontinuous Reception (DRX)",
"edrx": "Extended Discontinuous Reception (eDRX)" "edrx": "Extended Discontinuous Reception (eDRX)"
}, },
"edrx-cycle": "eDRX cycle in milliseconds", "edrx-cycle": "eDRX cycle",
"edrx-cycle-required": "eDRX cycle is required.", "edrx-cycle-required": "eDRX cycle is required.",
"edrx-cycle-pattern": "eDRX cycle must be a positive integer.", "edrx-cycle-pattern": "eDRX cycle must be a positive integer.",
"paging-transmission-window": "Paging Transmission Window in milliseconds", "edrx-cycle-min": "Minimum number of eDRX cycle is {{ min }} seconds.",
"paging-transmission-window": "Paging Transmission Window",
"paging-transmission-window-required": "Paging transmission window is required.", "paging-transmission-window-required": "Paging transmission window is required.",
"paging-transmission-window-pattern": "Paging transmission window must be a positive integer.", "paging-transmission-window-pattern": "Paging transmission window must be a positive integer.",
"psm-activity-timer": "PSM Activity Timer in milliseconds", "paging-transmission-window-min": "Minimum number ofpPaging transmission window is {{ min }} seconds.",
"psm-activity-timer": "PSM Activity Timer",
"psm-activity-timer-required": "PSM activity timer is required.", "psm-activity-timer-required": "PSM activity timer is required.",
"psm-activity-timer-pattern": "PSM activity timer must be a positive integer.", "psm-activity-timer-pattern": "PSM activity timer must be a positive integer.",
"psm-activity-timer-min": "Minimum number of PSM activity timer is {{ min }} seconds.",
"lwm2m": { "lwm2m": {
"object-list": "Object list", "object-list": "Object list",
"object-list-empty": "No objects selected.", "object-list-empty": "No objects selected.",
@ -2736,6 +2739,7 @@
} }
}, },
"timeunit": { "timeunit": {
"milliseconds": "Milliseconds",
"seconds": "Seconds", "seconds": "Seconds",
"minutes": "Minutes", "minutes": "Minutes",
"hours": "Hours", "hours": "Hours",