ui Value refactor
This commit is contained in:
parent
929ea7f802
commit
c3fc3ca3ca
15
src/main/angular/src/app/api/Value/Display.ts
Normal file
15
src/main/angular/src/app/api/Value/Display.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import {Value} from "./Value";
|
||||||
|
|
||||||
|
export class DisplayValue {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly title: string,
|
||||||
|
readonly value: Value,
|
||||||
|
readonly color: string,
|
||||||
|
) {
|
||||||
|
// -
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Display = DisplayValue | null;
|
||||||
115
src/main/angular/src/app/api/Value/Value.ts
Normal file
115
src/main/angular/src/app/api/Value/Value.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import {ValueConstant} from "./ValueConstant";
|
||||||
|
|
||||||
|
export class Value {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly date: Date | null,
|
||||||
|
readonly value: number | null,
|
||||||
|
readonly unit: string | null,
|
||||||
|
) {
|
||||||
|
// -
|
||||||
|
}
|
||||||
|
|
||||||
|
clampNonNegative(): Value {
|
||||||
|
return this.unary(v => v > 0 ? v : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
plus(other: Value): Value {
|
||||||
|
return this.binary(other, (a, b) => a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
minus(other: Value): Value {
|
||||||
|
return this.binary(other, (a, b) => a - b);
|
||||||
|
}
|
||||||
|
|
||||||
|
mul(other: Value): Value {
|
||||||
|
return this.binary(other, (a, b) => a * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
div(other: Value): Value {
|
||||||
|
return this.binary(other, (a, b) => a / b);
|
||||||
|
}
|
||||||
|
|
||||||
|
ne(other: Value): boolean {
|
||||||
|
return this.compare(other) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
eq(other: Value): boolean {
|
||||||
|
return this.compare(other) === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gt(other: Value): boolean {
|
||||||
|
return this.compare(other) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gte(other: Value): boolean {
|
||||||
|
return this.compare(other) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lt(other: Value): boolean {
|
||||||
|
return this.compare(other) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lte(other: Value): boolean {
|
||||||
|
return this.compare(other) <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unary(func: (v: number) => number): Value {
|
||||||
|
if (this.value === null) {
|
||||||
|
return new Value(null, null, null);
|
||||||
|
}
|
||||||
|
const value = func(this.value);
|
||||||
|
return new Value(this.date, value, this.unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
binary(other: Value, func: (a: number, b: number) => number): Value {
|
||||||
|
if (this.date === null || this.value === null || this.unit === null) {
|
||||||
|
return new Value(null, null, other.unit || null);
|
||||||
|
}
|
||||||
|
if (other.date === null || other.value === null || other.unit === null) {
|
||||||
|
return new Value(null, null, this.unit);
|
||||||
|
}
|
||||||
|
const oldestDate = this.getOldestDate(other);
|
||||||
|
const difference = func(this.value, other.value);
|
||||||
|
return new Value(oldestDate, difference, this.unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(other: Value, comparing?: (a: number, b: number) => number): number {
|
||||||
|
if (this.date === null || this.value === null || this.unit === null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (other.date === null || other.value === null || other.unit === null) {
|
||||||
|
return +1;
|
||||||
|
}
|
||||||
|
if (comparing === undefined) {
|
||||||
|
return this.value - other.value;
|
||||||
|
}
|
||||||
|
return comparing(this.value, other.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
color(middle: number, high: number, smallColor: string = '#23F', middleColor: string = 'orange', highColor: string = 'red'): string {
|
||||||
|
if (this.value === null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (Math.round(this.value) < middle) {
|
||||||
|
return smallColor;
|
||||||
|
} else if (Math.round(this.value) < high) {
|
||||||
|
return middleColor;
|
||||||
|
}
|
||||||
|
return highColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getOldestDate(other: Value) {
|
||||||
|
if (this.date === null || other.date === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (this instanceof ValueConstant === other instanceof ValueConstant) {
|
||||||
|
return this.date.getTime() < other.date.getTime() ? this.date : other.date;
|
||||||
|
} else if (this instanceof ValueConstant) {
|
||||||
|
return other.date;
|
||||||
|
}
|
||||||
|
return this.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
12
src/main/angular/src/app/api/Value/ValueConstant.ts
Normal file
12
src/main/angular/src/app/api/Value/ValueConstant.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import {Value} from "./Value";
|
||||||
|
|
||||||
|
export class ValueConstant extends Value {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
value: number | null,
|
||||||
|
unit: string | null,
|
||||||
|
) {
|
||||||
|
super(new Date(Date.now()), value, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,23 +0,0 @@
|
|||||||
export class Display {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly title: string,
|
|
||||||
readonly color: string,
|
|
||||||
readonly iValue: IValue | null,
|
|
||||||
) {
|
|
||||||
// -
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IValue {
|
|
||||||
|
|
||||||
readonly date: Date | null;
|
|
||||||
|
|
||||||
readonly value: number | null;
|
|
||||||
|
|
||||||
readonly unit: string | null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export type DisplayOrSeparator = Display | null;
|
|
||||||
@ -1,28 +1,21 @@
|
|||||||
import {Period} from "./consumption/period/Period";
|
import {Period} from "./consumption/period/Period";
|
||||||
import {validateDate, validateNumber, validateString} from "../validators";
|
import {validateDate, validateNumber, validateString} from "../validators";
|
||||||
|
import {Value} from "../Value/Value";
|
||||||
|
|
||||||
import {IValue} from "./IValue";
|
export class Series extends Value {
|
||||||
|
|
||||||
export class Series implements IValue {
|
static readonly EMPTY: Series = new Series(0, '', '', '', null, new Date(0), NaN);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly id: number,
|
readonly id: number,
|
||||||
readonly name: string,
|
readonly name: string,
|
||||||
readonly mode: string,
|
readonly mode: string,
|
||||||
readonly unit: string,
|
unit: string,
|
||||||
readonly period: Period | null,
|
readonly period: Period | null,
|
||||||
readonly lastDate: Date,
|
readonly lastDate: Date,
|
||||||
readonly lastValue: number,
|
readonly lastValue: number,
|
||||||
) {
|
) {
|
||||||
// -
|
super(lastDate, lastValue, unit);
|
||||||
}
|
|
||||||
|
|
||||||
get date(): Date {
|
|
||||||
return this.lastDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
get value(): number {
|
|
||||||
return this.lastValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json: any): Series {
|
static fromJson(json: any): Series {
|
||||||
|
|||||||
@ -1,68 +0,0 @@
|
|||||||
import {IValue} from "./IValue";
|
|
||||||
|
|
||||||
type GetValue = (v: number) => number | null;
|
|
||||||
|
|
||||||
type CombineValue = (a: number, b: number) => number;
|
|
||||||
|
|
||||||
function dateMin(a: Date, b: Date): Date {
|
|
||||||
if (a.getTime() < b.getTime()) {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Value implements IValue {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly date: Date | null,
|
|
||||||
readonly value: number | null,
|
|
||||||
readonly unit: string | null,
|
|
||||||
) {
|
|
||||||
// -
|
|
||||||
}
|
|
||||||
|
|
||||||
static positiveOnly(iValue: IValue | null): Value | null {
|
|
||||||
return this.map(iValue, v => v > 0 ? v : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static negativeOnlyToPositive(iValue: IValue | null): Value | null {
|
|
||||||
return this.map(iValue, v => v < 0 ? -v : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static map(iValue: IValue | null, mapping: GetValue): Value | null {
|
|
||||||
if (iValue === null || iValue.value === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const value = mapping(iValue.value);
|
|
||||||
return new Value(iValue.date, value, iValue.unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
static plus(a: IValue | null, b: IValue | null): Value | null {
|
|
||||||
return this.bi(a, b, (a, b) => a + b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static minus(a: IValue | null, b: IValue | null): Value | null {
|
|
||||||
return this.bi(a, b, (a, b) => a - b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static mul(a: IValue | null, b: IValue | null): Value | null {
|
|
||||||
return this.bi(a, b, (a, b) => a * b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static div(a: IValue | null, b: IValue | null): Value | null {
|
|
||||||
return this.bi(a, b, (a, b) => a / b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bi(a: IValue | null, b: IValue | null, combineValue: CombineValue) {
|
|
||||||
if (a === null) {
|
|
||||||
return new Value(null, null, b?.unit || null);
|
|
||||||
}
|
|
||||||
if (b === null) {
|
|
||||||
return new Value(null, null, a?.unit || null);
|
|
||||||
}
|
|
||||||
const oldestDate = a.date === null || b.date === null ? null : dateMin(a.date, b.date);
|
|
||||||
const difference = a.value === null || b.value === null ? null : combineValue(a.value, b.value);
|
|
||||||
return new Value(oldestDate, difference, a.unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -11,51 +11,51 @@ export class SeriesService {
|
|||||||
|
|
||||||
public series: Series[] = [];
|
public series: Series[] = [];
|
||||||
|
|
||||||
public gridPurchased: Series | null = null;
|
public gridPurchased: Series = Series.EMPTY;
|
||||||
|
|
||||||
public gridDelivered: Series | null = null;
|
public gridDelivered: Series = Series.EMPTY;
|
||||||
|
|
||||||
public photovoltaicProduced: Series | null = null;
|
public photovoltaicProduced: Series = Series.EMPTY;
|
||||||
|
|
||||||
public photovoltaicPower: Series | null = null;
|
public photovoltaicPower: Series = Series.EMPTY;
|
||||||
|
|
||||||
public gridPower: Series | null = null;
|
public gridPower: Series = Series.EMPTY;
|
||||||
|
|
||||||
public schlafzimmerTemperature: Series | null = null;
|
public schlafzimmerTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public schlafzimmerHumidityRelative: Series | null = null;
|
public schlafzimmerHumidityRelative: Series = Series.EMPTY;
|
||||||
|
|
||||||
public schlafzimmerHumidityAbsolute: Series | null = null;
|
public schlafzimmerHumidityAbsolute: Series = Series.EMPTY;
|
||||||
|
|
||||||
public outdoorTemperature: Series | null = null;
|
public outdoorTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public outdoorHumidityRelative: Series | null = null;
|
public outdoorHumidityRelative: Series = Series.EMPTY;
|
||||||
|
|
||||||
public outdoorHumidityAbsolute: Series | null = null;
|
public outdoorHumidityAbsolute: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingRoomTemperature: Series | null = null;
|
public heatingRoomTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingRoomHumidityRelative: Series | null = null;
|
public heatingRoomHumidityRelative: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingRoomHumidityAbsolute: Series | null = null;
|
public heatingRoomHumidityAbsolute: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingExhaustTemperature: Series | null = null;
|
public heatingExhaustTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingBufferSupplyTemperature: Series | null = null;
|
public heatingBufferSupplyTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingBufferReturnTemperature: Series | null = null;
|
public heatingBufferReturnTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingBufferColdTemperature: Series | null = null;
|
public heatingBufferColdTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingBufferInnerTemperature: Series | null = null;
|
public heatingBufferInnerTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingBufferHotTemperature: Series | null = null;
|
public heatingBufferHotTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingBufferCirculationTemperature: Series | null = null;
|
public heatingBufferCirculationTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingLoopSupplyTemperature: Series | null = null;
|
public heatingLoopSupplyTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
public heatingLoopReturnTemperature: Series | null = null;
|
public heatingLoopReturnTemperature: Series = Series.EMPTY;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly api: ApiService,
|
private readonly api: ApiService,
|
||||||
@ -100,7 +100,7 @@ export class SeriesService {
|
|||||||
this.heatingLoopReturnTemperature = this.seriesUpdate2(series, this.heatingLoopReturnTemperature, 'heating.loop.return.temperature');
|
this.heatingLoopReturnTemperature = this.seriesUpdate2(series, this.heatingLoopReturnTemperature, 'heating.loop.return.temperature');
|
||||||
}
|
}
|
||||||
|
|
||||||
private seriesUpdate2(fresh: Series, old: Series | null, name: string): Series | null {
|
private seriesUpdate2(fresh: Series, old: Series, name: string): Series {
|
||||||
if (fresh.name !== name) {
|
if (fresh.name !== name) {
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
<app-values-tile title="Luft" icon="air.svg" [displayList]="getDisplayList()" [now]="now"></app-values-tile>
|
<app-value-list title="Luft" icon="air.svg" [displayList]="getDisplayList()" [now]="now"></app-value-list>
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {ValuesTileComponent} from "../../../shared/values-tile/values-tile.component";
|
import {ValueListComponent} from "../../../shared/value-list/value-list.component";
|
||||||
import {Display, DisplayOrSeparator} from "../../../api/series/IValue";
|
|
||||||
import {SeriesService} from "../../../api/series/series.service";
|
import {SeriesService} from "../../../api/series/series.service";
|
||||||
|
import {DisplayValue, Display} from "../../../api/Value/Display";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard-air-tile',
|
selector: 'app-dashboard-air-tile',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
ValuesTileComponent
|
ValueListComponent
|
||||||
],
|
],
|
||||||
templateUrl: './dashboard-air-tile.component.html',
|
templateUrl: './dashboard-air-tile.component.html',
|
||||||
styleUrl: './dashboard-air-tile.component.less'
|
styleUrl: './dashboard-air-tile.component.less'
|
||||||
@ -23,29 +23,25 @@ export class DashboardAirTileComponent {
|
|||||||
// -
|
// -
|
||||||
}
|
}
|
||||||
|
|
||||||
getDisplayList(): DisplayOrSeparator[] {
|
getDisplayList(): Display[] {
|
||||||
const bedroomVent = this.seriesService.schlafzimmerHumidityAbsolute !== null && this.seriesService.schlafzimmerHumidityAbsolute.value !== null
|
const bedroomVent = this.seriesService.schlafzimmerHumidityAbsolute.gt(this.seriesService.outdoorHumidityAbsolute);
|
||||||
&& this.seriesService.outdoorHumidityAbsolute !== null && this.seriesService.outdoorHumidityAbsolute.value !== null
|
|
||||||
&& this.seriesService.schlafzimmerHumidityAbsolute.value > this.seriesService.outdoorHumidityAbsolute.value;
|
|
||||||
const bedroomVentColor = bedroomVent ? 'red' : '';
|
const bedroomVentColor = bedroomVent ? 'red' : '';
|
||||||
|
|
||||||
const heatingRoomVent = this.seriesService.heatingRoomHumidityAbsolute !== null && this.seriesService.heatingRoomHumidityAbsolute.value !== null
|
const heatingRoomVent = this.seriesService.heatingRoomHumidityAbsolute.gt(this.seriesService.outdoorHumidityAbsolute);
|
||||||
&& this.seriesService.outdoorHumidityAbsolute !== null && this.seriesService.outdoorHumidityAbsolute.value !== null
|
|
||||||
&& this.seriesService.heatingRoomHumidityAbsolute.value > this.seriesService.outdoorHumidityAbsolute.value;
|
|
||||||
const heatingRoomVentColor = heatingRoomVent ? 'red' : '';
|
const heatingRoomVentColor = heatingRoomVent ? 'red' : '';
|
||||||
|
|
||||||
return [
|
return [
|
||||||
new Display('Garten Temperatur', '', this.seriesService.outdoorTemperature),
|
new DisplayValue('Garten Temperatur', this.seriesService.outdoorTemperature, ''),
|
||||||
new Display('Garten Feucht. Relativ', '', this.seriesService.outdoorHumidityRelative),
|
new DisplayValue('Garten Feucht. Relativ', this.seriesService.outdoorHumidityRelative, ''),
|
||||||
new Display('Garten Feucht. Absolut', '', this.seriesService.outdoorHumidityAbsolute),
|
new DisplayValue('Garten Feucht. Absolut', this.seriesService.outdoorHumidityAbsolute, ''),
|
||||||
null,
|
null,
|
||||||
new Display('Schlaf. Temperatur', '', this.seriesService.schlafzimmerTemperature),
|
new DisplayValue('Schlaf. Temperatur', this.seriesService.schlafzimmerTemperature, ''),
|
||||||
new Display('Schlaf. Feucht. Relativ', '', this.seriesService.schlafzimmerHumidityRelative),
|
new DisplayValue('Schlaf. Feucht. Relativ', this.seriesService.schlafzimmerHumidityRelative, ''),
|
||||||
new Display('Schlaf. Feucht. Absolut', bedroomVentColor, this.seriesService.schlafzimmerHumidityAbsolute),
|
new DisplayValue('Schlaf. Feucht. Absolut', this.seriesService.schlafzimmerHumidityAbsolute, bedroomVentColor),
|
||||||
null,
|
null,
|
||||||
new Display('Heiz. Temperatur', '', this.seriesService.heatingRoomTemperature),
|
new DisplayValue('Heiz. Temperatur', this.seriesService.heatingRoomTemperature, ''),
|
||||||
new Display('Heiz. Feucht. Relativ', '', this.seriesService.heatingRoomHumidityRelative),
|
new DisplayValue('Heiz. Feucht. Relativ', this.seriesService.heatingRoomHumidityRelative, ''),
|
||||||
new Display('Heiz. Feucht. Absolut', heatingRoomVentColor, this.seriesService.heatingRoomHumidityAbsolute),
|
new DisplayValue('Heiz. Feucht. Absolut', this.seriesService.heatingRoomHumidityAbsolute, heatingRoomVentColor),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import {Component, OnDestroy, OnInit} from '@angular/core';
|
import {Component, OnDestroy, OnInit} from '@angular/core';
|
||||||
import {JsonPipe, NgForOf} from "@angular/common";
|
import {JsonPipe, NgForOf} from "@angular/common";
|
||||||
import {ValuesTileComponent} from "../../shared/values-tile/values-tile.component";
|
import {ValueListComponent} from "../../shared/value-list/value-list.component";
|
||||||
import {DashboardElectricityTileComponent} from "./electricity/dashboard-electricity-tile.component";
|
import {DashboardElectricityTileComponent} from "./electricity/dashboard-electricity-tile.component";
|
||||||
import {DashboardAirTileComponent} from "./air/dashboard-air-tile.component";
|
import {DashboardAirTileComponent} from "./air/dashboard-air-tile.component";
|
||||||
import {Subscription, timer} from "rxjs";
|
import {Subscription, timer} from "rxjs";
|
||||||
@ -13,7 +13,7 @@ const UPDATE_INTERVAL_MILLIS = 1000;
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
NgForOf,
|
NgForOf,
|
||||||
ValuesTileComponent,
|
ValueListComponent,
|
||||||
JsonPipe,
|
JsonPipe,
|
||||||
DashboardElectricityTileComponent,
|
DashboardElectricityTileComponent,
|
||||||
DashboardAirTileComponent,
|
DashboardAirTileComponent,
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
<app-values-tile title="Elektrizität" icon="electricity.svg" [displayList]="getDisplayList()" [now]="now"></app-values-tile>
|
<app-value-list title="Elektrizität" icon="electricity.svg" [displayList]="getDisplayList()" [now]="now"></app-value-list>
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {ValuesTileComponent} from "../../../shared/values-tile/values-tile.component";
|
import {ValueListComponent} from "../../../shared/value-list/value-list.component";
|
||||||
import {Display, DisplayOrSeparator} from "../../../api/series/IValue";
|
|
||||||
import {Value} from "../../../api/series/Value";
|
|
||||||
import {SeriesService} from "../../../api/series/series.service";
|
import {SeriesService} from "../../../api/series/series.service";
|
||||||
|
import {DisplayValue, Display} from "../../../api/Value/Display";
|
||||||
|
import {ValueConstant} from "../../../api/Value/ValueConstant";
|
||||||
|
|
||||||
const PURCHASING_MUCH = 200;
|
const PURCHASING_MUCH = 200;
|
||||||
|
|
||||||
const PRODUCED_UNTIL_METER_CHANGE = 287.995;
|
const PRODUCED_BEFORE_METER_CHANGE = new ValueConstant(287.995, "kWh");
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dashboard-electricity-tile',
|
selector: 'app-dashboard-electricity-tile',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
ValuesTileComponent
|
ValueListComponent
|
||||||
],
|
],
|
||||||
templateUrl: './dashboard-electricity-tile.component.html',
|
templateUrl: './dashboard-electricity-tile.component.html',
|
||||||
styleUrl: './dashboard-electricity-tile.component.less'
|
styleUrl: './dashboard-electricity-tile.component.less'
|
||||||
@ -28,30 +28,24 @@ export class DashboardElectricityTileComponent {
|
|||||||
// -
|
// -
|
||||||
}
|
}
|
||||||
|
|
||||||
getDisplayList(): DisplayOrSeparator[] {
|
getDisplayList(): Display[] {
|
||||||
const consumptionPower = Value.positiveOnly(Value.plus(this.seriesService.photovoltaicPower, this.seriesService.gridPower));
|
const consumptionPower = this.seriesService.photovoltaicPower.plus(this.seriesService.gridPower).clampNonNegative();
|
||||||
const selfConsumed = Value.map(this.seriesService.photovoltaicProduced, producedTotal => {
|
const producedAfterChange = this.seriesService.photovoltaicProduced.minus(PRODUCED_BEFORE_METER_CHANGE);
|
||||||
if (this.seriesService.gridDelivered === null || this.seriesService.gridDelivered.value === null) {
|
const selfAfterChange = producedAfterChange.minus(this.seriesService.gridDelivered);
|
||||||
return null;
|
const selfRatio = selfAfterChange.div(producedAfterChange);
|
||||||
}
|
const selfConsumed = selfRatio.mul(this.seriesService.photovoltaicProduced);
|
||||||
const producedAfterChange = producedTotal - PRODUCED_UNTIL_METER_CHANGE;
|
|
||||||
const deliveredAfterChange = this.seriesService.gridDelivered?.value;
|
|
||||||
const selfAfterChange = producedAfterChange - deliveredAfterChange;
|
|
||||||
const selfRatio = selfAfterChange / producedAfterChange;
|
|
||||||
return selfRatio * producedTotal;
|
|
||||||
});
|
|
||||||
|
|
||||||
const gridColor = this.getGridPowerColor();
|
const gridColor = this.getGridPowerColor();
|
||||||
const productionColor = this.getProductionPowerColor();
|
const productionColor = this.getProductionPowerColor();
|
||||||
return [
|
return [
|
||||||
new Display('Bezogen', '', this.seriesService.gridPurchased),
|
new DisplayValue('Bezogen', this.seriesService.gridPurchased, ''),
|
||||||
new Display('Eingespeist', '', this.seriesService.gridDelivered),
|
new DisplayValue('Eingespeist', this.seriesService.gridDelivered, ''),
|
||||||
new Display('Produziert', '', this.seriesService.photovoltaicProduced),
|
new DisplayValue('Produziert', this.seriesService.photovoltaicProduced, ''),
|
||||||
new Display('Selbst verbraucht', '', selfConsumed),
|
new DisplayValue('Selbst verbraucht', selfConsumed, ''),
|
||||||
null,
|
null,
|
||||||
new Display('Produktion', productionColor, this.seriesService.photovoltaicPower),
|
new DisplayValue('Produktion', this.seriesService.photovoltaicPower, productionColor),
|
||||||
new Display('Netz', gridColor, this.seriesService.gridPower),
|
new DisplayValue('Netz', this.seriesService.gridPower, gridColor),
|
||||||
new Display('Verbrauch', '', consumptionPower),
|
new DisplayValue('Verbrauch', consumptionPower, ''),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
<app-values-tile title="Heizung" icon="fire.svg" [maxAgeSeconds]="125" [displayList]="getDisplayList()" [now]="now"></app-values-tile>
|
<app-value-list title="Heizung" icon="fire.svg" [maxAgeSeconds]="125" [displayList]="getDisplayList()" [now]="now"></app-value-list>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {ValuesTileComponent} from "../../../shared/values-tile/values-tile.component";
|
import {ValueListComponent} from "../../../shared/value-list/value-list.component";
|
||||||
import {Display, DisplayOrSeparator, IValue} from "../../../api/series/IValue";
|
|
||||||
import {SeriesService} from "../../../api/series/series.service";
|
import {SeriesService} from "../../../api/series/series.service";
|
||||||
|
import {DisplayValue, Display} from "../../../api/Value/Display";
|
||||||
|
|
||||||
const WARM = 25;
|
const WARM = 25;
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ const HOT = 55;
|
|||||||
selector: 'app-dashboard-heating-tile',
|
selector: 'app-dashboard-heating-tile',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
ValuesTileComponent
|
ValueListComponent
|
||||||
],
|
],
|
||||||
templateUrl: './dashboard-heating-tile.component.html',
|
templateUrl: './dashboard-heating-tile.component.html',
|
||||||
styleUrl: './dashboard-heating-tile.component.less'
|
styleUrl: './dashboard-heating-tile.component.less'
|
||||||
@ -27,33 +27,21 @@ export class DashboardHeatingTileComponent {
|
|||||||
// -
|
// -
|
||||||
}
|
}
|
||||||
|
|
||||||
getDisplayList(): DisplayOrSeparator[] {
|
getDisplayList(): Display[] {
|
||||||
return [
|
return [
|
||||||
new Display('Abgas', this.color(WARM, HOT, this.seriesService.heatingExhaustTemperature, ''), this.seriesService.heatingExhaustTemperature),
|
new DisplayValue('Abgas', this.seriesService.heatingExhaustTemperature, this.seriesService.heatingExhaustTemperature.color(WARM, HOT, '')),
|
||||||
null,
|
null,
|
||||||
new Display('Heizkreis Vorlauf', this.color(WARM, HOT, this.seriesService.heatingLoopSupplyTemperature), this.seriesService.heatingLoopSupplyTemperature),
|
new DisplayValue('Heizkreis Vorlauf', this.seriesService.heatingLoopSupplyTemperature, this.seriesService.heatingLoopSupplyTemperature.color(WARM, HOT)),
|
||||||
new Display('Heizkreis Rücklauf', this.color(WARM, HOT, this.seriesService.heatingLoopReturnTemperature), this.seriesService.heatingLoopReturnTemperature),
|
new DisplayValue('Heizkreis Rücklauf', this.seriesService.heatingLoopReturnTemperature, this.seriesService.heatingLoopReturnTemperature.color(WARM, HOT)),
|
||||||
null,
|
null,
|
||||||
new Display('Puffer Vorlauf', this.color(WARM, HOT, this.seriesService.heatingBufferSupplyTemperature), this.seriesService.heatingBufferSupplyTemperature),
|
new DisplayValue('Puffer Vorlauf', this.seriesService.heatingBufferSupplyTemperature, this.seriesService.heatingBufferSupplyTemperature.color(WARM, HOT)),
|
||||||
new Display('Puffer Rücklauf', this.color(WARM, HOT, this.seriesService.heatingBufferReturnTemperature), this.seriesService.heatingBufferReturnTemperature),
|
new DisplayValue('Puffer Rücklauf', this.seriesService.heatingBufferReturnTemperature, this.seriesService.heatingBufferReturnTemperature.color(WARM, HOT)),
|
||||||
null,
|
null,
|
||||||
new Display('Puffer Kalt', this.color(WARM, HOT, this.seriesService.heatingBufferColdTemperature), this.seriesService.heatingBufferColdTemperature),
|
new DisplayValue('Puffer Kalt', this.seriesService.heatingBufferColdTemperature, this.seriesService.heatingBufferColdTemperature.color(WARM, HOT)),
|
||||||
new Display('Puffer Speicher', this.color(WARM, HOT, this.seriesService.heatingBufferInnerTemperature), this.seriesService.heatingBufferInnerTemperature),
|
new DisplayValue('Puffer Speicher', this.seriesService.heatingBufferInnerTemperature, this.seriesService.heatingBufferInnerTemperature.color(WARM, HOT)),
|
||||||
new Display('Puffer Warm', this.color(WARM, HOT, this.seriesService.heatingBufferHotTemperature), this.seriesService.heatingBufferHotTemperature),
|
new DisplayValue('Puffer Warm', this.seriesService.heatingBufferHotTemperature, this.seriesService.heatingBufferHotTemperature.color(WARM, HOT)),
|
||||||
new Display('Puffer Zirkulation', this.color(WARM, HOT, this.seriesService.heatingBufferCirculationTemperature), this.seriesService.heatingBufferCirculationTemperature),
|
new DisplayValue('Puffer Zirkulation', this.seriesService.heatingBufferCirculationTemperature, this.seriesService.heatingBufferCirculationTemperature.color(WARM, HOT)),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private color(middle: number, high: number, value: IValue | null, smallColor: string = '#23F', middleColor: string = 'orange', highColor: string = 'red'): string {
|
|
||||||
if (value === null || value.value === null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if (Math.round(value.value) < middle) {
|
|
||||||
return smallColor;
|
|
||||||
} else if (Math.round(value.value) < high) {
|
|
||||||
return middleColor;
|
|
||||||
}
|
|
||||||
return highColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,10 +8,10 @@
|
|||||||
<tr class="rate" *ngIf="display" [style.color]="display.color">
|
<tr class="rate" *ngIf="display" [style.color]="display.color">
|
||||||
<th>{{ display.title }}</th>
|
<th>{{ display.title }}</th>
|
||||||
<td class="v">
|
<td class="v">
|
||||||
{{ display?.iValue?.value | number:'0.0-0' }}
|
{{ display?.value?.value | number:'0.0-0' }}
|
||||||
</td>
|
</td>
|
||||||
<td class="u">
|
<td class="u">
|
||||||
{{ display?.iValue?.unit }}
|
{{ display?.value?.unit }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr *ngIf="display === null">
|
<tr *ngIf="display === null">
|
||||||
@ -1,19 +1,19 @@
|
|||||||
import {Component, Input} from '@angular/core';
|
import {Component, Input} from '@angular/core';
|
||||||
import {DecimalPipe, NgForOf, NgIf} from "@angular/common";
|
import {DecimalPipe, NgForOf, NgIf} from "@angular/common";
|
||||||
import {DisplayOrSeparator} from "../../api/series/IValue";
|
import {Display} from "../../api/Value/Display";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-values-tile',
|
selector: 'app-value-list',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
NgIf,
|
NgIf,
|
||||||
DecimalPipe,
|
DecimalPipe,
|
||||||
NgForOf
|
NgForOf
|
||||||
],
|
],
|
||||||
templateUrl: './values-tile.component.html',
|
templateUrl: './value-list.component.html',
|
||||||
styleUrl: './values-tile.component.less'
|
styleUrl: './value-list.component.less'
|
||||||
})
|
})
|
||||||
export class ValuesTileComponent {
|
export class ValueListComponent {
|
||||||
|
|
||||||
protected valid: boolean = false;
|
protected valid: boolean = false;
|
||||||
|
|
||||||
@ -35,15 +35,15 @@ export class ValuesTileComponent {
|
|||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
protected displayList_: DisplayOrSeparator[] = [];
|
protected displayList_: Display[] = [];
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
set displayList(seriesList: DisplayOrSeparator[]) {
|
set displayList(seriesList: Display[]) {
|
||||||
this.displayList_ = seriesList;
|
this.displayList_ = seriesList;
|
||||||
this.displayUpdate();
|
this.displayUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
get displayList(): DisplayOrSeparator[] {
|
get displayList(): Display[] {
|
||||||
return this.displayList_;
|
return this.displayList_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ export class ValuesTileComponent {
|
|||||||
maxAgeSeconds: number = 10;
|
maxAgeSeconds: number = 10;
|
||||||
|
|
||||||
private displayUpdate() {
|
private displayUpdate() {
|
||||||
this.valid = this.displayList.some(d => !!d && !!d.iValue && !!d.iValue.date && (this.now.getTime() - d.iValue.date.getTime()) <= this.maxAgeSeconds * 1000)
|
this.valid = this.displayList.some(d => !!d && !!d.value && !!d.value.date && (this.now.getTime() - d.value.date.getTime()) <= this.maxAgeSeconds * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user