Data/src/main/angular/src/app/series/series.service.ts

114 lines
3.5 KiB
TypeScript

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<Series>[] = [];
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<Series>): Subscription {
const wrapper: Next<Series> = 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<Series[]>) {
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<AggregationWrapperDto>) {
this.api.getSingle(['Series', 'agg', 'all', alignment.name, 'offset', offset], j => AggregationWrapperDto.fromJson(j, this.locale), next);
}
}