Browse Source

Improve timezone offset handling for latest values and alarm widgets. Improve timezone selector - add local browser time info on empty value.

pull/4266/head
Igor Kulikov 5 years ago
parent
commit
a17c5b7757
  1. 6
      ui-ngx/src/app/core/api/alarm-data-subscription.ts
  2. 66
      ui-ngx/src/app/core/api/entity-data-subscription.ts
  3. 5
      ui-ngx/src/app/core/api/entity-data.service.ts
  4. 40
      ui-ngx/src/app/core/api/widget-subscription.ts
  5. 5
      ui-ngx/src/app/shared/components/time/timewindow-panel.component.html
  6. 59
      ui-ngx/src/app/shared/components/time/timezone-select.component.ts
  7. 72
      ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts
  8. 23
      ui-ngx/src/app/shared/models/time/time.models.ts
  9. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

6
ui-ngx/src/app/core/api/alarm-data-subscription.ts

@ -130,6 +130,7 @@ export class AlarmDataSubscription {
this.alarmDataCommand.query.pageLink.timeWindow = this.subsTw.realtimeWindowMs;
}
this.subscriber.setTsOffset(this.subsTw.tsOffset);
this.subscriber.subscriptionCommands.push(this.alarmDataCommand);
this.subscriber.alarmData$.subscribe((alarmDataUpdate) => {
@ -143,8 +144,11 @@ export class AlarmDataSubscription {
this.subscriber.subscribe();
} else if (this.datasourceType === DatasourceType.function) {
const alarm = deepClone(simulatedAlarm);
alarm.createdTime += this.subsTw.tsOffset;
alarm.startTs += this.subsTw.tsOffset;
const pageData: PageData<AlarmData> = {
data: [{...simulatedAlarm, entityId: '1', latest: {}}],
data: [{...alarm, entityId: '1', latest: {}}],
hasNext: false,
totalElements: 1,
totalPages: 1

66
ui-ngx/src/app/core/api/entity-data-subscription.ts

@ -15,7 +15,7 @@
///
import { DataSet, DataSetHolder, DatasourceType, widgetType } from '@shared/models/widget.models';
import { AggregationType, SubscriptionTimewindow } from '@shared/models/time/time.models';
import { AggregationType, getCurrentTime, SubscriptionTimewindow } from '@shared/models/time/time.models';
import {
EntityData,
EntityDataPageLink,
@ -74,6 +74,7 @@ export interface EntityDataSubscriptionOptions {
keyFilters?: Array<KeyFilter>;
additionalKeyFilters?: Array<KeyFilter>;
subscriptionTimewindow?: SubscriptionTimewindow;
latestTsOffset?: number;
}
export class EntityDataSubscription {
@ -95,6 +96,7 @@ export class EntityDataSubscription {
private entityDataResolveSubject: Subject<EntityDataLoadResult>;
private pageData: PageData<EntityData>;
private subsTw: SubscriptionTimewindow;
private latestTsOffset: number;
private dataAggregators: Array<DataAggregator>;
private dataKeys: {[key: string]: Array<SubscriptionDataKey> | SubscriptionDataKey} = {};
private datasourceData: {[index: number]: {[key: string]: DataSetHolder}};
@ -177,6 +179,7 @@ export class EntityDataSubscription {
this.started = true;
this.dataResolved = true;
this.subsTw = this.entityDataSubscriptionOptions.subscriptionTimewindow;
this.latestTsOffset = this.entityDataSubscriptionOptions.latestTsOffset;
this.history = this.entityDataSubscriptionOptions.subscriptionTimewindow &&
isObject(this.entityDataSubscriptionOptions.subscriptionTimewindow.fixedWindow);
this.realtime = this.entityDataSubscriptionOptions.subscriptionTimewindow &&
@ -237,7 +240,12 @@ export class EntityDataSubscription {
};
if (this.entityDataSubscriptionOptions.isPaginatedDataSubscription) {
this.prepareSubscriptionCommands();
this.prepareSubscriptionCommands(this.dataCommand);
if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) {
this.subscriber.setTsOffset(this.subsTw.tsOffset);
} else {
this.subscriber.setTsOffset(this.latestTsOffset);
}
}
this.subscriber.subscriptionCommands.push(this.dataCommand);
@ -276,9 +284,15 @@ export class EntityDataSubscription {
this.subscriber.subscriptionCommands = [this.dataCommand];
}
});
this.subscriber.subscribe();
} else if (this.datasourceType === DatasourceType.function) {
let tsOffset = 0;
if (this.entityDataSubscriptionOptions.type === widgetType.latest) {
tsOffset = this.entityDataSubscriptionOptions.latestTsOffset;
} else if (this.entityDataSubscriptionOptions.subscriptionTimewindow) {
tsOffset = this.entityDataSubscriptionOptions.subscriptionTimewindow.tsOffset;
}
const entityData: EntityData = {
entityId: {
id: NULL_UUID,
@ -289,7 +303,7 @@ export class EntityDataSubscription {
};
const name = DatasourceType.function;
entityData.latest[EntityKeyType.ENTITY_FIELD] = {
name: {ts: Date.now(), value: name}
name: {ts: Date.now() + tsOffset, value: name}
};
const pageData: PageData<EntityData> = {
data: [entityData],
@ -299,7 +313,9 @@ export class EntityDataSubscription {
};
this.onPageData(pageData);
} else if (this.datasourceType === DatasourceType.entityCount) {
this.latestTsOffset = this.entityDataSubscriptionOptions.latestTsOffset;
this.subscriber = new TelemetrySubscriber(this.telemetryService);
this.subscriber.setTsOffset(this.latestTsOffset);
this.countCommand = new EntityCountCmd();
let keyFilters = this.entityDataSubscriptionOptions.keyFilters;
if (this.entityDataSubscriptionOptions.additionalKeyFilters) {
@ -332,13 +348,13 @@ export class EntityDataSubscription {
latest: {
[EntityKeyType.ENTITY_FIELD]: {
name: {
ts: Date.now(),
ts: Date.now() + this.latestTsOffset,
value: DatasourceType.entityCount
}
},
[EntityKeyType.COUNT]: {
[countKey.name]: {
ts: Date.now(),
ts: Date.now() + this.latestTsOffset,
value: entityCountUpdate.count + ''
}
}
@ -359,7 +375,7 @@ export class EntityDataSubscription {
latest: {
[EntityKeyType.COUNT]: {
[countKey.name]: {
ts: Date.now(),
ts: Date.now() + this.latestTsOffset,
value: entityCountUpdate.count + ''
}
}
@ -384,6 +400,7 @@ export class EntityDataSubscription {
return;
}
this.subsTw = this.entityDataSubscriptionOptions.subscriptionTimewindow;
this.latestTsOffset = this.entityDataSubscriptionOptions.latestTsOffset;
this.history = this.entityDataSubscriptionOptions.subscriptionTimewindow &&
isObject(this.entityDataSubscriptionOptions.subscriptionTimewindow.fixedWindow);
this.realtime = this.entityDataSubscriptionOptions.subscriptionTimewindow &&
@ -394,22 +411,38 @@ export class EntityDataSubscription {
if (this.datasourceType === DatasourceType.entity) {
this.subsCommand = new EntityDataCmd();
this.subsCommand.cmdId = this.dataCommand.cmdId;
this.prepareSubscriptionCommands();
if (!this.subsCommand.isEmpty()) {
this.prepareSubscriptionCommands(this.subsCommand);
let latestTsOffsetChanged = false;
if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) {
this.subscriber.setTsOffset(this.subsTw.tsOffset);
} else {
latestTsOffsetChanged = this.subscriber.setTsOffset(this.latestTsOffset);
}
if (latestTsOffsetChanged) {
if (this.listener.initialPageDataChanged) {
this.listener.initialPageDataChanged(this.pageData);
}
} else if (!this.subsCommand.isEmpty()) {
this.subscriber.subscriptionCommands = [this.subsCommand];
this.subscriber.update();
}
} else if (this.datasourceType === DatasourceType.entityCount) {
if (this.subscriber.setTsOffset(this.latestTsOffset)) {
if (this.listener.initialPageDataChanged) {
this.listener.initialPageDataChanged(this.pageData);
}
}
} else if (this.datasourceType === DatasourceType.function) {
this.startFunction();
}
this.started = true;
}
private prepareSubscriptionCommands() {
private prepareSubscriptionCommands(cmd: EntityDataCmd) {
if (this.entityDataSubscriptionOptions.type === widgetType.timeseries) {
if (this.tsFields.length > 0) {
if (this.history) {
this.subsCommand.historyCmd = {
cmd.historyCmd = {
keys: this.tsFields.map(key => key.key),
startTs: this.subsTw.fixedWindow.startTimeMs,
endTs: this.subsTw.fixedWindow.endTimeMs,
@ -419,7 +452,7 @@ export class EntityDataSubscription {
fetchLatestPreviousPoint: this.subsTw.aggregation.stateData
};
} else {
this.subsCommand.tsCmd = {
cmd.tsCmd = {
keys: this.tsFields.map(key => key.key),
startTs: this.subsTw.startTs,
timeWindow: this.subsTw.aggregation.timeWindow,
@ -430,10 +463,9 @@ export class EntityDataSubscription {
};
}
}
this.subscriber.setTsOffset(this.subsTw.tsOffset);
} else if (this.entityDataSubscriptionOptions.type === widgetType.latest) {
if (this.latestValues.length > 0) {
this.subsCommand.latestCmd = {
cmd.latestCmd = {
keys: this.latestValues
};
}
@ -783,7 +815,7 @@ export class EntityDataSubscription {
} else {
prevSeries = [0, 0];
}
const time = Date.now();
const time = Date.now() + this.latestTsOffset;
const value = dataKey.func(time, prevSeries[1]);
const series: [number, any] = [time, value];
this.datasourceData[0][dataKey.key].data = [series];
@ -838,6 +870,10 @@ export class EntityDataSubscription {
endTime = this.entityDataSubscriptionOptions.subscriptionTimewindow.fixedWindow.endTimeMs +
this.entityDataSubscriptionOptions.subscriptionTimewindow.tsOffset;
}
if (this.entityDataSubscriptionOptions.subscriptionTimewindow.quickInterval) {
const currentTime = getCurrentTime().valueOf() + this.entityDataSubscriptionOptions.subscriptionTimewindow.tsOffset;
endTime = Math.min(currentTime, endTime);
}
}
generatedData.data[`${dataKey.name}_${dataKey.index}`] = this.generateSeries(dataKey, index, startTime, endTime);
}

5
ui-ngx/src/app/core/api/entity-data.service.ts

@ -32,6 +32,7 @@ import { Observable, of } from 'rxjs';
export interface EntityDataListener {
subscriptionType: widgetType;
subscriptionTimewindow?: SubscriptionTimewindow;
latestTsOffset?: number;
configDatasource: Datasource;
configDatasourceIndex: number;
dataLoaded: (pageData: PageData<EntityData>,
@ -92,6 +93,8 @@ export class EntityDataService {
if (listener.subscription) {
if (listener.subscriptionType === widgetType.timeseries) {
listener.subscriptionOptions.subscriptionTimewindow = deepClone(listener.subscriptionTimewindow);
} else if (listener.subscriptionType === widgetType.latest) {
listener.subscriptionOptions.latestTsOffset = listener.latestTsOffset;
}
listener.subscription.start();
}
@ -118,6 +121,8 @@ export class EntityDataService {
listener.subscription = new EntityDataSubscription(listener, this.telemetryService, this.utils);
if (listener.subscriptionType === widgetType.timeseries) {
listener.subscriptionOptions.subscriptionTimewindow = deepClone(listener.subscriptionTimewindow);
} else if (listener.subscriptionType === widgetType.latest) {
listener.subscriptionOptions.latestTsOffset = listener.latestTsOffset;
}
return listener.subscription.subscribe();
}

40
ui-ngx/src/app/core/api/widget-subscription.ts

@ -39,8 +39,10 @@ import { HttpErrorResponse } from '@angular/common/http';
import {
calculateIntervalEndTime,
calculateIntervalStartTime,
calculateTsOffset,
createSubscriptionTimewindow,
createTimewindowForComparison, getCurrentTime,
createTimewindowForComparison,
getCurrentTime,
SubscriptionTimewindow,
Timewindow,
toHistoryTimewindow,
@ -79,8 +81,10 @@ export class WidgetSubscription implements IWidgetSubscription {
timeWindow: WidgetTimewindow;
originalTimewindow: Timewindow;
timeWindowConfig: Timewindow;
timezone: string;
subscriptionTimewindow: SubscriptionTimewindow;
useDashboardTimewindow: boolean;
tsOffset = 0;
hasDataPageLink: boolean;
singleEntity: boolean;
@ -213,6 +217,10 @@ export class WidgetSubscription implements IWidgetSubscription {
this.timeWindow = {};
this.useDashboardTimewindow = options.useDashboardTimewindow;
this.stateData = options.stateData;
if (this.type === widgetType.latest) {
this.timezone = options.dashboardTimewindow.timezone;
this.updateTsOffset();
}
if (this.useDashboardTimewindow) {
this.timeWindowConfig = deepClone(options.dashboardTimewindow);
} else {
@ -578,11 +586,16 @@ export class WidgetSubscription implements IWidgetSubscription {
if (!isEqual(this.timeWindowConfig, newDashboardTimewindow) && newDashboardTimewindow) {
this.timeWindowConfig = deepClone(newDashboardTimewindow);
this.update();
return true;
}
}
} else if (this.type === widgetType.latest) {
if (newDashboardTimewindow && this.timezone !== newDashboardTimewindow.timezone) {
this.timezone = newDashboardTimewindow.timezone;
if (this.updateTsOffset()) {
this.update();
}
}
}
return false;
}
updateDataVisibility(index: number): void {
@ -815,6 +828,7 @@ export class WidgetSubscription implements IWidgetSubscription {
configDatasource: datasource,
configDatasourceIndex: datasourceIndex,
subscriptionTimewindow: this.subscriptionTimewindow,
latestTsOffset: this.tsOffset,
dataLoaded: (pageData, data1, datasourceIndex1, pageLink1) => {
this.dataLoaded(pageData, data1, datasourceIndex1, pageLink1, true);
},
@ -882,25 +896,28 @@ export class WidgetSubscription implements IWidgetSubscription {
}
private dataSubscribe() {
this.updateDataTimewindow();
if (!this.hasDataPageLink) {
if (this.type === widgetType.timeseries && this.timeWindowConfig) {
this.updateDataTimewindow();
if (this.subscriptionTimewindow.fixedWindow) {
if (this.type === widgetType.timeseries && this.timeWindowConfig && this.subscriptionTimewindow.fixedWindow) {
this.onDataUpdated();
}
}
const forceUpdate = !this.datasources.length;
const notifyDataLoaded = !this.entityDataListeners.filter((listener) => listener.subscription ? true : false).length;
this.entityDataListeners.forEach((listener) => {
if (this.comparisonEnabled && listener.configDatasource.isAdditional) {
listener.subscriptionTimewindow = this.timewindowForComparison;
} else {
listener.subscriptionTimewindow = this.subscriptionTimewindow;
listener.latestTsOffset = this.tsOffset;
}
this.ctx.entityDataService.startSubscription(listener);
});
if (forceUpdate) {
this.onDataUpdated();
}
if (notifyDataLoaded) {
this.notifyDataLoaded();
}
}
}
@ -1102,6 +1119,15 @@ export class WidgetSubscription implements IWidgetSubscription {
}
}
private updateTsOffset(): boolean {
const newOffset = calculateTsOffset(this.timezone);
if (this.tsOffset !== newOffset) {
this.tsOffset = newOffset;
return true;
}
return false;
}
private updateRealtimeSubscription(subscriptionTimewindow?: SubscriptionTimewindow): SubscriptionTimewindow {
if (subscriptionTimewindow) {
this.subscriptionTimewindow = subscriptionTimewindow;

5
ui-ngx/src/app/shared/components/time/timewindow-panel.component.html

@ -133,7 +133,7 @@
<mat-checkbox [ngModelOptions]="{standalone: true}" [(ngModel)]="timewindow.hideAggInterval"
(ngModelChange)="onHideAggIntervalChanged()"></mat-checkbox>
</section>
<section fxLayout="column" [fxShow]="isEdit || !timewindow.hideAggInterval">
<section fxLayout="column" fxFlex [fxShow]="isEdit || !timewindow.hideAggInterval">
<div class="limit-slider-container"
fxLayout="row" fxLayoutAlign="start center">
<span translate>aggregation.limit</span>
@ -184,7 +184,8 @@
(ngModelChange)="onHideTimezoneChanged()"></mat-checkbox>
</section>
<tb-timezone-select fxFlex [fxShow]="isEdit || !timewindow.hideTimezone"
formControlName="timezone">
localBrowserTimezonePlaceholderOnEmpty="true"
formControlName="timezone">
</tb-timezone-select>
</div>
<div fxLayout="row" class="tb-panel-actions" fxLayoutAlign="end center">

59
ui-ngx/src/app/shared/components/time/timezone-select.component.ts

@ -23,7 +23,8 @@ import { AppState } from '@app/core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { MatAutocompleteTrigger } from '@angular/material/autocomplete';
import { getTimezoneInfo, getTimezones, TimezoneInfo } from '@shared/models/time/time.models';
import { getDefaultTimezoneInfo, getTimezoneInfo, getTimezones, TimezoneInfo } from '@shared/models/time/time.models';
import { deepClone } from '@core/utils';
@Component({
selector: 'tb-timezone-select',
@ -68,6 +69,15 @@ export class TimezoneSelectComponent implements ControlValueAccessor, OnInit, Af
this.userTimezoneByDefaultValue = coerceBooleanProperty(value);
}
private localBrowserTimezonePlaceholderOnEmptyValue: boolean;
get localBrowserTimezonePlaceholderOnEmpty(): boolean {
return this.localBrowserTimezonePlaceholderOnEmptyValue;
}
@Input()
set localBrowserTimezonePlaceholderOnEmpty(value: boolean) {
this.localBrowserTimezonePlaceholderOnEmptyValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
@ -81,6 +91,10 @@ export class TimezoneSelectComponent implements ControlValueAccessor, OnInit, Af
private dirty = false;
private localBrowserTimezoneInfoPlaceholder: TimezoneInfo;
private timezones: Array<TimezoneInfo>;
private propagateChange = (v: any) => { };
constructor(private store: Store<AppState>,
@ -146,7 +160,11 @@ export class TimezoneSelectComponent implements ControlValueAccessor, OnInit, Af
}
} else {
this.modelValue = null;
this.selectTimezoneFormGroup.get('timezone').patchValue('', {emitEvent: false});
if (this.localBrowserTimezonePlaceholderOnEmptyValue) {
this.selectTimezoneFormGroup.get('timezone').patchValue(this.getLocalBrowserTimezoneInfoPlaceholder(), {emitEvent: false});
} else {
this.selectTimezoneFormGroup.get('timezone').patchValue('', {emitEvent: false});
}
}
this.dirty = true;
}
@ -162,11 +180,17 @@ export class TimezoneSelectComponent implements ControlValueAccessor, OnInit, Af
if (this.ignoreClosePanel) {
this.ignoreClosePanel = false;
} else {
if (!this.modelValue && (this.defaultTimezoneId || this.userTimezoneByDefaultValue)) {
const defaultTimezoneInfo = getTimezoneInfo(this.defaultTimezoneId, this.defaultTimezoneId, this.userTimezoneByDefaultValue);
if (defaultTimezoneInfo !== null) {
if (!this.modelValue) {
if (this.defaultTimezoneId || this.userTimezoneByDefaultValue) {
const defaultTimezoneInfo = getTimezoneInfo(this.defaultTimezoneId, this.defaultTimezoneId, this.userTimezoneByDefaultValue);
if (defaultTimezoneInfo !== null) {
this.ngZone.run(() => {
this.selectTimezoneFormGroup.get('timezone').reset(defaultTimezoneInfo, {emitEvent: true});
});
}
} else if (this.localBrowserTimezonePlaceholderOnEmptyValue) {
this.ngZone.run(() => {
this.selectTimezoneFormGroup.get('timezone').reset(defaultTimezoneInfo, {emitEvent: true});
this.selectTimezoneFormGroup.get('timezone').reset(this.getLocalBrowserTimezoneInfoPlaceholder(), {emitEvent: true});
});
}
}
@ -187,10 +211,10 @@ export class TimezoneSelectComponent implements ControlValueAccessor, OnInit, Af
fetchTimezones(searchText?: string): Observable<Array<TimezoneInfo>> {
this.searchText = searchText;
if (searchText && searchText.length) {
return of(getTimezones().filter((timezoneInfo) =>
return of(this.loadTimezones().filter((timezoneInfo) =>
timezoneInfo.name.toLowerCase().includes(searchText.toLowerCase())));
}
return of(getTimezones());
return of(this.loadTimezones());
}
clear() {
@ -200,4 +224,23 @@ export class TimezoneSelectComponent implements ControlValueAccessor, OnInit, Af
}, 0);
}
private loadTimezones(): Array<TimezoneInfo> {
if (!this.timezones) {
this.timezones = [];
if (this.localBrowserTimezonePlaceholderOnEmptyValue) {
this.timezones.push(this.getLocalBrowserTimezoneInfoPlaceholder());
}
this.timezones.push(...getTimezones());
}
return this.timezones;
}
private getLocalBrowserTimezoneInfoPlaceholder(): TimezoneInfo {
if (!this.localBrowserTimezoneInfoPlaceholder) {
this.localBrowserTimezoneInfoPlaceholder = deepClone(getDefaultTimezoneInfo());
this.localBrowserTimezoneInfoPlaceholder.id = null;
this.localBrowserTimezoneInfoPlaceholder.name = this.translate.instant('timezone.browser-time');
}
return this.localBrowserTimezoneInfoPlaceholder;
}
}

72
ui-ngx/src/app/shared/models/telemetry/telemetry.models.ts

@ -30,6 +30,9 @@ import {
TsValue
} from '@shared/models/query/query.models';
import { PageData } from '@shared/models/page/page-data';
import { alarmFields } from '@shared/models/alarm.models';
import { entityFields } from '@shared/models/entity.models';
import { isUndefined } from '@core/utils';
export enum DataKeyType {
timeseries = 'timeseries',
@ -446,7 +449,9 @@ export class EntityDataUpdate extends DataUpdate<EntityData> {
for (const key of Object.keys(entityData.timeseries)) {
const tsValues = entityData.timeseries[key];
for (const tsValue of tsValues) {
tsValue.ts += tsOffset;
if (tsValue.ts) {
tsValue.ts += tsOffset;
}
}
}
}
@ -455,13 +460,17 @@ export class EntityDataUpdate extends DataUpdate<EntityData> {
const keyTypeValues = entityData.latest[entityKeyType];
for (const key of Object.keys(keyTypeValues)) {
const tsValue = keyTypeValues[key];
tsValue.ts += tsOffset;
if (tsValue.ts) {
tsValue.ts += tsOffset;
}
if (key === entityFields.createdTime.keyName && tsValue.value) {
tsValue.value = (Number(tsValue.value) + tsOffset) + '';
}
}
}
}
}
}
}
export class AlarmDataUpdate extends DataUpdate<AlarmData> {
@ -473,6 +482,48 @@ export class AlarmDataUpdate extends DataUpdate<AlarmData> {
this.allowedEntities = msg.allowedEntities;
this.totalEntities = msg.totalEntities;
}
public prepareData(tsOffset: number) {
if (this.data) {
this.processAlarmData(this.data.data, tsOffset);
}
if (this.update) {
this.processAlarmData(this.update, tsOffset);
}
}
private processAlarmData(data: Array<AlarmData>, tsOffset: number) {
for (const alarmData of data) {
alarmData.createdTime += tsOffset;
if (alarmData.ackTs) {
alarmData.ackTs += tsOffset;
}
if (alarmData.clearTs) {
alarmData.clearTs += tsOffset;
}
if (alarmData.endTs) {
alarmData.endTs += tsOffset;
}
if (alarmData.latest) {
for (const entityKeyType of Object.keys(alarmData.latest)) {
const keyTypeValues = alarmData.latest[entityKeyType];
for (const key of Object.keys(keyTypeValues)) {
const tsValue = keyTypeValues[key];
if (tsValue.ts) {
tsValue.ts += tsOffset;
}
if (key in [entityFields.createdTime.keyName,
alarmFields.startTime.keyName,
alarmFields.endTime.keyName,
alarmFields.ackTime.keyName,
alarmFields.clearTime.keyName] && tsValue.value) {
tsValue.value = (Number(tsValue.value) + tsOffset) + '';
}
}
}
}
}
}
}
export class EntityCountUpdate extends CmdUpdate {
@ -500,7 +551,7 @@ export class TelemetrySubscriber {
private zone: NgZone;
private tsOffset = 0;
private tsOffset = undefined;
public subscriptionCommands: Array<WebsocketCmd>;
@ -556,8 +607,14 @@ export class TelemetrySubscriber {
this.reconnectSubject.complete();
}
public setTsOffset(tsOffset: number) {
this.tsOffset = tsOffset;
public setTsOffset(tsOffset: number): boolean {
if (this.tsOffset !== tsOffset) {
const changed = !isUndefined(this.tsOffset);
this.tsOffset = tsOffset;
return changed;
} else {
return false;
}
}
public onData(message: SubscriptionUpdate) {
@ -598,6 +655,9 @@ export class TelemetrySubscriber {
}
public onAlarmData(message: AlarmDataUpdate) {
if (this.tsOffset) {
message.prepareData(this.tsOffset);
}
if (this.zone) {
this.zone.run(
() => {

23
ui-ngx/src/app/shared/models/time/time.models.ts

@ -318,6 +318,16 @@ export function toHistoryTimewindow(timewindow: Timewindow, startTimeMs: number,
return historyTimewindow;
}
export function calculateTsOffset(timezone?: string): number {
if (timezone) {
const tz = getTimezone(timezone);
const localOffset = moment().utcOffset();
return (tz.utcOffset() - localOffset) * 60 * 1000;
} else {
return 0;
}
}
export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: number, stateData: boolean,
timeService: TimeService): SubscriptionTimewindow {
const subscriptionTimewindow: SubscriptionTimewindow = {
@ -329,13 +339,8 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num
type: AggregationType.AVG
},
timezone: timewindow.timezone,
tsOffset: 0
tsOffset: calculateTsOffset(timewindow.timezone)
};
if (timewindow.timezone) {
const tz = getTimezone(timewindow.timezone);
const localOffset = moment().utcOffset();
subscriptionTimewindow.tsOffset = (tz.utcOffset() - localOffset) * 60 * 1000;
}
let aggTimewindow = 0;
if (stateData) {
subscriptionTimewindow.aggregation.type = AggregationType.NONE;
@ -407,6 +412,7 @@ export function createSubscriptionTimewindow(timewindow: Timewindow, stDiff: num
endTimeMs: calculateIntervalEndTime(timewindow.history.quickInterval, currentDate)
};
aggTimewindow = subscriptionTimewindow.fixedWindow.endTimeMs - subscriptionTimewindow.fixedWindow.startTimeMs;
subscriptionTimewindow.quickInterval = timewindow.history.quickInterval;
} else {
subscriptionTimewindow.fixedWindow = {
startTimeMs: timewindow.history.fixedTimewindow.startTimeMs - subscriptionTimewindow.tsOffset,
@ -768,6 +774,11 @@ export function getTimezoneInfo(timezoneId: string, defaultTimezoneId?: string,
return foundTimezone;
}
export function getDefaultTimezoneInfo(): TimezoneInfo {
const userTimezone = getDefaultTimezone();
return getTimezoneInfo(userTimezone);
}
export function getDefaultTimezone(): string {
if (!defaultTimezone) {
defaultTimezone = monentTz.tz.guess();

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

@ -1988,7 +1988,8 @@
"timezone": "Timezone",
"select-timezone": "Select timezone",
"no-timezones-matching": "No timezones matching '{{timezone}}' were found.",
"timezone-required": "Timezone is required."
"timezone-required": "Timezone is required.",
"browser-time": "Browser Time"
},
"queue": {
"select_name": "Select queue name",

Loading…
Cancel
Save