import {Inject, Injectable, LOCALE_ID} from '@angular/core'; import {ApiService} from '../core/api.service'; import {Alignment} from './Alignment'; import {AggregationWrapperDto} from './AggregationWrapperDto'; import {Subscription} from 'rxjs'; import {Series} from './Series'; import {SeriesWrapper} from './SeriesWrapper'; import {Next} from '../core/types'; @Injectable({ providedIn: 'root' }) export class SeriesService { private readonly clientSubscriptions: Subscription[] = []; private readonly subs: Subscription[] = []; private readonly clientCallbacks: Next[] = []; readonly powerConsumed: SeriesWrapper = new SeriesWrapper("power/consumed", this.onSubscribe, this.onUnsubscribe); readonly powerProduced: SeriesWrapper = new SeriesWrapper("power/produced", this.onSubscribe, this.onUnsubscribe); readonly powerSelf: SeriesWrapper = new SeriesWrapper("power/self", this.onSubscribe, this.onUnsubscribe); readonly powerBalance: SeriesWrapper = new SeriesWrapper("power/balance", this.onSubscribe, this.onUnsubscribe); readonly liveValues: SeriesWrapper[] = [ this.powerConsumed, this.powerProduced, this.powerSelf, this.powerBalance, ] constructor( @Inject(LOCALE_ID) readonly locale: string, protected readonly api: ApiService, ) { // } private onSubscribe(subscription: Subscription): Subscription { this.clientSubscriptions.push(subscription); this.ensureApiSubscribed(); return subscription; } private onUnsubscribe(subscription: Subscription): Subscription { this.clientSubscriptions.splice(this.clientSubscriptions.indexOf(subscription), 1); if (this.clientSubscriptions.length === 0) { this.ensureApiUnsubscribed(); } return subscription; } private ensureApiSubscribed() { if (this.subs.length !== 0) { return; } this.subs.push(this.api.subscribe(['Series'], j => Series.fromJson(j, this.locale), series => this.update(series))); this.subs.push(this.api.subscribeConnection(connected => { if (connected) { this.all(); } else { this.liveValues.forEach(liveValue => liveValue.series = null); } })); } private ensureApiUnsubscribed() { if (this.subs.length <= 0) { return; } this.subs.forEach(sub => sub.unsubscribe()); this.subs.length = 0; } private update(series: Series) { this.liveValues .filter(liveValue => liveValue.name === series.name) .forEach(liveValue => liveValue.series = series); this.clientCallbacks.forEach(next => next(series)); } subscribeAny(next?: Next): Subscription { const wrapper: Next = series => { // to let clientCallbacks only contain unique instances if (next) { next(series); } }; this.clientCallbacks.push(wrapper); const subscription = new Subscription(() => { this.onUnsubscribe(subscription); this.clientCallbacks.splice(this.clientCallbacks.indexOf(wrapper), 1); }); return this.onSubscribe(subscription); } all(next?: Next) { this.api.getList(['Series', 'all'], j => Series.fromJson(j, this.locale), list => { list.forEach(item => this.update(item)); if (next) { next(list); } }); } aggregations(alignment: Alignment, offset: number, next: Next) { this.api.getSingle(['Series', 'agg', 'all', alignment.name, 'offset', offset], j => AggregationWrapperDto.fromJson(j, this.locale), next); } }