diff --git a/ui-ngx/src/app/core/services/utils.service.ts b/ui-ngx/src/app/core/services/utils.service.ts index b901b87328..c02abcdd39 100644 --- a/ui-ngx/src/app/core/services/utils.service.ts +++ b/ui-ngx/src/app/core/services/utils.service.ts @@ -43,6 +43,15 @@ import { WidgetInfo } from '@home/models/widget-component.models'; import jsonSchemaDefaults from 'json-schema-defaults'; import materialIconsCodepoints from '!raw-loader!./material-icons-codepoints.raw'; import { Observable, of, ReplaySubject } from 'rxjs'; +import { publishReplay, refCount } from 'rxjs/operators'; +import { WidgetContext } from '@app/modules/home/models/widget-component.models'; +import { + AttributeData, + TelemetrySubscriber, + TelemetryType, + LatestTelemetry +} from '@shared/models/telemetry/telemetry.models'; +import { EntityId } from '@shared/models/id/entity-id'; const i18nRegExp = new RegExp(`{${i18nPrefix}:[^{}]+}`, 'g'); @@ -479,4 +488,34 @@ export class UtilsService { return defaultValue; } } + + public getEntityIdFromDatasource(dataSource: Datasource): EntityId { + return {id: dataSource.entityId, entityType: dataSource.entityType}; + } + + public createTelemetrySubscriber(ctx: WidgetContext, + entityId?: EntityId, + type: TelemetryType = LatestTelemetry.LATEST_TELEMETRY, + keys: string[] = null): TelemetrySubscriber { + if (!entityId && ctx.datasources.length > 0) { + entityId = this.getEntityIdFromDatasource(ctx.datasources[0]); + } + return TelemetrySubscriber.createEntityAttributesSubscription(ctx.telemetryWsService, entityId, type, ctx.ngZone, keys); + } + + public subscribeToEntityTelemetry(ctx: WidgetContext, + entityId?: EntityId, + type: TelemetryType = LatestTelemetry.LATEST_TELEMETRY, + keys: string[] = null): Observable> { + const subscription = this.createTelemetrySubscriber(ctx, entityId, type, keys); + if (!ctx.telemetrySubscribers) { + ctx.telemetrySubscribers = []; + } + ctx.telemetrySubscribers.push(subscription); + subscription.subscribe(); + return subscription.attributeData$().pipe( + publishReplay(1), + refCount() + ); + } } diff --git a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts index 59b1959269..040e27b2ff 100644 --- a/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/dynamic-widget.component.ts @@ -40,6 +40,7 @@ import { AuthService } from '@core/auth/auth.service'; import { DialogService } from '@core/services/dialog.service'; import { CustomDialogService } from '@home/components/widget/dialog/custom-dialog.service'; import { ResourceService } from '@core/http/resource.service'; +import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service'; import { DatePipe } from '@angular/common'; import { TranslateService } from '@ngx-translate/core'; import { DomSanitizer } from '@angular/platform-browser'; @@ -80,6 +81,7 @@ export class DynamicWidgetComponent extends PageComponent implements IDynamicWid this.ctx.dialogs = $injector.get(DialogService); this.ctx.customDialog = $injector.get(CustomDialogService); this.ctx.resourceService = $injector.get(ResourceService); + this.ctx.telemetryWsService = $injector.get(TelemetryWebsocketService); this.ctx.date = $injector.get(DatePipe); this.ctx.translate = $injector.get(TranslateService); this.ctx.http = $injector.get(HttpClient); @@ -100,7 +102,9 @@ export class DynamicWidgetComponent extends PageComponent implements IDynamicWid } ngOnDestroy(): void { - + if (this.ctx.telemetrySubscribers) { + this.ctx.telemetrySubscribers.forEach(item => item.unsubscribe()); + } } clearRpcError() { diff --git a/ui-ngx/src/app/modules/home/models/services.map.ts b/ui-ngx/src/app/modules/home/models/services.map.ts index 93ec69da61..7514e972b5 100644 --- a/ui-ngx/src/app/modules/home/models/services.map.ts +++ b/ui-ngx/src/app/modules/home/models/services.map.ts @@ -39,6 +39,7 @@ import { OtaPackageService } from '@core/http/ota-package.service'; import { AuthService } from '@core/auth/auth.service'; import { ResourceService } from '@core/http/resource.service'; import { TwoFactorAuthenticationService } from '@core/http/two-factor-authentication.service'; +import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service'; export const ServicesMap = new Map>( [ @@ -65,6 +66,7 @@ export const ServicesMap = new Map>( ['otaPackageService', OtaPackageService], ['authService', AuthService], ['resourceService', ResourceService], - ['twoFactorAuthenticationService', TwoFactorAuthenticationService] + ['twoFactorAuthenticationService', TwoFactorAuthenticationService], + ['telemetryWsService', TelemetryWebsocketService] ] ); diff --git a/ui-ngx/src/app/modules/home/models/widget-component.models.ts b/ui-ngx/src/app/modules/home/models/widget-component.models.ts index afd50d1c82..813b3b6927 100644 --- a/ui-ngx/src/app/modules/home/models/widget-component.models.ts +++ b/ui-ngx/src/app/modules/home/models/widget-component.models.ts @@ -75,6 +75,7 @@ import { DialogService } from '@core/services/dialog.service'; import { CustomDialogService } from '@home/components/widget/dialog/custom-dialog.service'; import { AuthService } from '@core/auth/auth.service'; import { ResourceService } from '@core/http/resource.service'; +import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service'; import { DatePipe } from '@angular/common'; import { TranslateService } from '@ngx-translate/core'; import { PageLink, TimePageLink } from '@shared/models/page/page-link'; @@ -87,6 +88,7 @@ import * as RxJSOperators from 'rxjs/operators'; import { TbPopoverComponent } from '@shared/components/popover.component'; import { EntityId } from '@shared/models/id/entity-id'; import { AlarmQuery, AlarmSearchStatus, AlarmStatus} from '@app/shared/models/alarm.models'; +import { TelemetrySubscriber } from '@app/shared/public-api'; export interface IWidgetAction { name: string; @@ -177,6 +179,8 @@ export class WidgetContext { dialogs: DialogService; customDialog: CustomDialogService; resourceService: ResourceService; + telemetryWsService: TelemetryWebsocketService; + telemetrySubscribers?: TelemetrySubscriber[]; date: DatePipe; translate: TranslateService; http: HttpClient;