Skip to content

Commit

Permalink
UI: add charts and other small changes (#1107)
Browse files Browse the repository at this point in the history
-change of phase 1 color to orange (red is too much in use for charge values)
-small code fixes
-add chpsoc history chart
-add heating element chart
-adjustments on heating element widget
-automatic value update for history widgets and charts
  • Loading branch information
fabianfnc authored Apr 23, 2020
1 parent 0e1d704 commit 35fdc7a
Show file tree
Hide file tree
Showing 54 changed files with 1,083 additions and 515 deletions.
34 changes: 32 additions & 2 deletions ui/src/app/edge/history/abstracthistorychart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,30 @@ import { JsonrpcResponseError } from "../../shared/jsonrpc/base";
import { QueryHistoricTimeseriesDataRequest } from "../../shared/jsonrpc/request/queryHistoricTimeseriesDataRequest";
import { QueryHistoricTimeseriesDataResponse } from "../../shared/jsonrpc/response/queryHistoricTimeseriesDataResponse";
import { TranslateService } from '@ngx-translate/core';
import { interval, Subject, fromEvent } from 'rxjs';
import { takeUntil, debounceTime, delay } from 'rxjs/operators';

export abstract class AbstractHistoryChart {


public loading: boolean = true;

//observable is used to fetch new chart data every 5 minutes
private refreshChartData = interval(300000);
//observable is used to refresh chart height dependend on the window size
private refreshChartHeight = fromEvent(window, 'resize', null, null);

private ngUnsubscribe: Subject<void> = new Subject<void>();

protected labels: Date[] = [];
protected datasets: Dataset[] = EMPTY_DATASET;
protected options: ChartOptions;
protected colors = []

// Colors for Phase 1-3
protected phase1Color = {
backgroundColor: 'rgba(255,0,0,0.05)',
borderColor: 'rgba(255,0,0,1)',
backgroundColor: 'rgba(255,127,80,0.05)',
borderColor: 'rgba(255,127,80,1)',
}
protected phase2Color = {
backgroundColor: 'rgba(0,0,255,0.1)',
Expand Down Expand Up @@ -70,6 +80,26 @@ export abstract class AbstractHistoryChart {
});
}

/**
* Subscribes to 5 minute Interval Observable and Window Resize Observable to fetch new data and resize chart if needed
*/
protected subscribeChartRefresh() {
this.refreshChartData.pipe(takeUntil(this.ngUnsubscribe)).subscribe(() => {
this.updateChart()
})
this.refreshChartHeight.pipe(takeUntil(this.ngUnsubscribe), debounceTime(200), delay(100)).subscribe(() => {
this.getChartHeight();
});
}

/**
* Unsubscribes to 5 minute Interval Observable and Window Resize Observable
*/
protected unsubscribeChartRefresh() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}

/**
* Sets the Label of Chart
*/
Expand Down
76 changes: 76 additions & 0 deletions ui/src/app/edge/history/abstracthistorywidget.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { interval, Subject } from 'rxjs';
import { JsonrpcResponseError } from 'src/app/shared/jsonrpc/base';
import { QueryHistoricTimeseriesDataRequest } from 'src/app/shared/jsonrpc/request/queryHistoricTimeseriesDataRequest';
import { QueryHistoricTimeseriesDataResponse } from 'src/app/shared/jsonrpc/response/queryHistoricTimeseriesDataResponse';
import { Service, ChannelAddress, Edge, EdgeConfig } from 'src/app/shared/shared';
import { takeUntil } from 'rxjs/operators';

export abstract class AbstractHistoryWidget {

//observable is used to fetch new widget data every 5 minutes
private refreshWidgetData = interval(300000);

private ngUnsubscribe: Subject<void> = new Subject<void>();

constructor(
protected service: Service,
) { }

/**
* Subscribes to 5 minute Interval Observable to update data in Flat Widget
*/
protected subscribeWidgetRefresh() {
this.refreshWidgetData.pipe(takeUntil(this.ngUnsubscribe)).subscribe(() => {
this.updateValues()
})
}

/**
* Unsubscribes to 5 minute Interval Observable
*/
protected unsubscribeWidgetRefresh() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}

/**
* Sends the Historic Timeseries Data Query and makes sure the result is not empty.
*
* @param fromDate the From-Date
* @param toDate the To-Date
* @param edge the current Edge
* @param ws the websocket
*/
protected queryHistoricTimeseriesData(fromDate: Date, toDate: Date): Promise<QueryHistoricTimeseriesDataResponse> {
return new Promise((resolve, reject) => {
this.service.getCurrentEdge().then(edge => {
this.service.getConfig().then(config => {
this.getChannelAddresses(edge, config).then(channelAddresses => {
let request = new QueryHistoricTimeseriesDataRequest(fromDate, toDate, channelAddresses);
edge.sendRequest(this.service.websocket, request).then(response => {
let result = (response as QueryHistoricTimeseriesDataResponse).result;
if (Object.keys(result.data).length != 0 && Object.keys(result.timestamps).length != 0) {
resolve(response as QueryHistoricTimeseriesDataResponse);
} else {
reject(new JsonrpcResponseError(response.id, { code: 0, message: "Result was empty" }));
}
}).catch(reason => reject(reason));
}).catch(reason => reject(reason));
})
});
});
}

/**
* Gets the ChannelAdresses that should be queried.
*
* @param edge the current Edge
* @param config the EdgeConfig
*/
protected abstract getChannelAddresses(edge: Edge, config: EdgeConfig): Promise<ChannelAddress[]>;

/**
* Updates and Fills the Chart
*/
protected abstract updateValues()
}
5 changes: 5 additions & 0 deletions ui/src/app/edge/history/autarchy/chart.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export class AutarchyChartComponent extends AbstractHistoryChart implements OnIn

ngOnInit() {
this.service.setCurrentComponent('', this.route);
this.subscribeChartRefresh()
}

ngOnDestroy() {
this.unsubscribeChartRefresh()
}

protected updateChart() {
Expand Down
44 changes: 28 additions & 16 deletions ui/src/app/edge/history/autarchy/widget.component.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { ActivatedRoute } from '@angular/router';
import { AutarchyModalComponent } from './modal/modal.component';
import { ChannelAddress, Edge, Service } from '../../../shared/shared';
import { ChannelAddress, Edge, Service, EdgeConfig } from '../../../shared/shared';
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { CurrentData } from 'src/app/shared/edge/currentdata';
import { DefaultTypes } from 'src/app/shared/service/defaulttypes';
import { ModalController } from '@ionic/angular';
import { AbstractHistoryWidget } from '../abstracthistorywidget';

@Component({
selector: AutarchyWidgetComponent.SELECTOR,
templateUrl: './widget.component.html'
})
export class AutarchyWidgetComponent implements OnInit, OnChanges {
export class AutarchyWidgetComponent extends AbstractHistoryWidget implements OnInit, OnChanges {

@Input() public period: DefaultTypes.HistoryPeriod;

Expand All @@ -23,32 +24,43 @@ export class AutarchyWidgetComponent implements OnInit, OnChanges {
public service: Service,
private route: ActivatedRoute,
public modalCtrl: ModalController,
) { }
) {
super(service);
}

ngOnInit() {
this.service.setCurrentComponent('', this.route).then(response => {
this.edge = response;
});
this.subscribeWidgetRefresh()
}

ngOnDestroy() {
this.unsubscribeWidgetRefresh()
}

ngOnChanges() {
this.updateValues();
};

updateValues() {
let channels: ChannelAddress[] = [
new ChannelAddress('_sum', 'GridBuyActiveEnergy'),
new ChannelAddress('_sum', 'ConsumptionActiveEnergy'),
];
this.service.queryEnergy(this.period.from, this.period.to, channels).then(response => {
this.service.getConfig().then(() => {
let result = response.result;
this.autarchyValue = CurrentData.calculateAutarchy(result.data['_sum/GridBuyActiveEnergy'] / 1000, result.data['_sum/ConsumptionActiveEnergy'] / 1000)
}).catch(reason => {
console.error(reason); // TODO error message
protected updateValues() {
this.service.getConfig().then(config => {
this.getChannelAddresses(this.edge, config).then(channels => {
this.service.queryEnergy(this.period.from, this.period.to, channels).then(response => {
let result = response.result;
this.autarchyValue = CurrentData.calculateAutarchy(result.data['_sum/GridBuyActiveEnergy'] / 1000, result.data['_sum/ConsumptionActiveEnergy'] / 1000);
})
});
}).catch(reason => {
console.error(reason); // TODO error message
})
}

protected getChannelAddresses(edge: Edge, config: EdgeConfig): Promise<ChannelAddress[]> {
return new Promise((resolve) => {
let channels: ChannelAddress[] = [
new ChannelAddress('_sum', 'GridBuyActiveEnergy'),
new ChannelAddress('_sum', 'ConsumptionActiveEnergy'),
];
resolve(channels);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ export class ChannelthresholdSingleChartComponent extends AbstractHistoryChart i

ngOnInit() {
this.service.setCurrentComponent('', this.route);
this.subscribeChartRefresh()
}

ngOnDestroy() {
this.unsubscribeChartRefresh()
}

protected updateChart() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export class ChannelthresholdTotalChartComponent extends AbstractHistoryChart im

ngOnInit() {
this.service.setCurrentComponent('', this.route);
this.subscribeChartRefresh()
}

ngOnDestroy() {
this.unsubscribeChartRefresh()
}

protected updateChart() {
Expand Down
52 changes: 19 additions & 33 deletions ui/src/app/edge/history/channelthreshold/widget.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import { ChannelAddress, Edge, EdgeConfig, Service } from '../../../shared/share
import { ChannelthresholdModalComponent } from './modal/modal.component';
import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { DefaultTypes } from 'src/app/shared/service/defaulttypes';
import { JsonrpcResponseError } from 'src/app/shared/jsonrpc/base';
import { ModalController } from '@ionic/angular';
import { QueryHistoricTimeseriesDataRequest } from 'src/app/shared/jsonrpc/request/queryHistoricTimeseriesDataRequest';
import { QueryHistoricTimeseriesDataResponse } from 'src/app/shared/jsonrpc/response/queryHistoricTimeseriesDataResponse';
import { AbstractHistoryWidget } from '../abstracthistorywidget';

@Component({
selector: ChanneltresholdWidgetComponent.SELECTOR,
templateUrl: './widget.component.html'
})
export class ChanneltresholdWidgetComponent implements OnInit, OnChanges {
export class ChanneltresholdWidgetComponent extends AbstractHistoryWidget implements OnInit, OnChanges {

@Input() public period: DefaultTypes.HistoryPeriod;
@Input() private componentId: string;
Expand All @@ -29,7 +28,9 @@ export class ChanneltresholdWidgetComponent implements OnInit, OnChanges {
public service: Service,
private route: ActivatedRoute,
public modalCtrl: ModalController,
) { }
) {
super(service);
}

ngOnInit() {
this.service.setCurrentComponent('', this.route).then(response => {
Expand All @@ -39,44 +40,29 @@ export class ChanneltresholdWidgetComponent implements OnInit, OnChanges {
this.component = config.getComponent(this.componentId);
})
});
this.subscribeWidgetRefresh()
}

ngOnDestroy() {
this.unsubscribeWidgetRefresh()
}

ngOnChanges() {
this.updateValues();
};


updateValues() {
this.queryHistoricTimeseriesData(this.service.historyPeriod.from, this.service.historyPeriod.to);
};

// Gather result & timestamps to calculate effective active time in %
queryHistoricTimeseriesData(fromDate: Date, toDate: Date): Promise<QueryHistoricTimeseriesDataResponse> {
return new Promise((resolve, reject) => {
this.service.getCurrentEdge().then(edge => {
this.service.getConfig().then(config => {
this.getChannelAddresses(config).then(channelAddresses => {
let request = new QueryHistoricTimeseriesDataRequest(fromDate, toDate, channelAddresses);
edge.sendRequest(this.service.websocket, request).then(response => {
let result = (response as QueryHistoricTimeseriesDataResponse).result;

let outputChannel = ChannelAddress.fromString(config.getComponentProperties(this.componentId)['outputChannelAddress']);
this.activeTimeOverPeriod = calculateActiveTimeOverPeriod(outputChannel, result);

if (Object.keys(result.data).length != 0 && Object.keys(result.timestamps).length != 0) {
resolve(response as QueryHistoricTimeseriesDataResponse);
} else {
reject(new JsonrpcResponseError(response.id, { code: 0, message: "Result was empty" }));
}
}).catch(reason => reject(reason));
}).catch(reason => reject(reason));
})
});
protected updateValues() {
// Gather result & timestamps to calculate effective active time in %
this.queryHistoricTimeseriesData(this.service.historyPeriod.from, this.service.historyPeriod.to).then(response => {
let result = (response as QueryHistoricTimeseriesDataResponse).result;
this.service.getConfig().then(config => {
let outputChannel = ChannelAddress.fromString(config.getComponentProperties(this.componentId)['outputChannelAddress']);
this.activeTimeOverPeriod = calculateActiveTimeOverPeriod(outputChannel, result);
})
});
}
};

getChannelAddresses(config: EdgeConfig): Promise<ChannelAddress[]> {
protected getChannelAddresses(edge: Edge, config: EdgeConfig): Promise<ChannelAddress[]> {
return new Promise((resolve) => {
const outputChannel = ChannelAddress.fromString(config.getComponentProperties(this.componentId)['outputChannelAddress']);
let channeladdresses = [outputChannel];
Expand Down
Loading

0 comments on commit 35fdc7a

Please sign in to comment.