From 320729647e9538479901b95083b762db82b0918a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Wed, 29 Oct 2025 16:45:28 +0100 Subject: [PATCH] REFACTOR: points (request, response) --- .../history/graph/simple-plot.component.html | 9 ++ .../history/graph/simple-plot.component.less | 9 ++ .../history/graph/simple-plot.component.ts | 70 ++++++++++++ .../detail/history/series-history.html | 1 + .../location/detail/history/series-history.ts | 24 +++-- .../app/location/detail/location-detail.html | 4 +- .../app/location/detail/location-detail.ts | 3 +- .../angular/src/app/point/PointResponse.ts | 23 ++++ src/main/angular/src/app/point/PointSeries.ts | 22 ++++ .../angular/src/app/point/point-service.ts | 29 +++++ src/main/angular/src/app/series/History.ts | 22 ---- src/main/angular/src/app/series/Interval.ts | 8 ++ src/main/angular/src/app/series/Series.ts | 10 +- .../angular/src/app/series/series-service.ts | 14 --- src/main/angular/src/main.ts | 6 +- src/main/java/de/ph87/data/DemoService.java | 2 +- src/main/java/de/ph87/data/plot/PlotDto.java | 5 +- .../de/ph87/data/plot/PlotRepository.java | 2 +- .../java/de/ph87/data/plot/PlotService.java | 2 +- .../ph87/data/plot/axis/graph/GraphDto.java | 6 +- .../de/ph87/data/point/IPointRequest.java | 27 +++++ .../de/ph87/data/point/PointController.java | 23 ++++ .../ph87/data/point/PointRequestRelative.java | 38 +++++++ .../de/ph87/data/point/PointResponse.java | 17 +++ .../java/de/ph87/data/point/PointSeries.java | 16 +++ .../java/de/ph87/data/point/PointService.java | 47 ++++++++ .../java/de/ph87/data/series/HistoryDto.java | 22 ---- .../de/ph87/data/series/SeriesController.java | 30 ------ .../java/de/ph87/data/series/SeriesDto.java | 7 -- .../de/ph87/data/series/SeriesRepository.java | 10 +- .../de/ph87/data/series/data/bool/Bool.java | 6 +- .../ph87/data/series/data/bool/BoolDto.java | 2 +- .../ph87/data/series/data/bool/BoolPoint.java | 51 ++------- .../ph87/data/series/data/bool/BoolRepo.java | 4 +- .../data/series/data/bool/BoolService.java | 15 +-- .../data/series/data/delta/DeltaPoint.java | 28 +---- .../data/series/data/delta/DeltaRepo.java | 4 +- .../data/series/data/delta/DeltaService.java | 16 +-- .../data/series/data/delta/ISeriesPoint.java | 18 ++++ .../data/delta/ISeriesPointSerializer.java | 20 ++++ .../series/data/varying/VaryingPoint.java | 41 ++----- .../data/series/data/varying/VaryingRepo.java | 4 +- .../series/data/varying/VaryingService.java | 16 +-- .../series/point/AllSeriesPointRequest.java | 34 ------ .../series/point/AllSeriesPointResponse.java | 30 ------ .../series/point/ISeriesPointRequest.java | 19 ---- .../series/point/OneSeriesPointsRequest.java | 64 ----------- .../series/point/OneSeriesPointsResponse.java | 14 --- .../OneSeriesPointsResponseSerializer.java | 21 ---- .../ph87/data/series/point/SeriesPoint.java | 66 ------------ .../data/series/point/SeriesPointService.java | 100 ------------------ .../java/de/ph87/data/topic/TopicType.java | 2 +- .../de/ph87/data/weather/WeatherService.java | 2 +- 53 files changed, 470 insertions(+), 615 deletions(-) create mode 100644 src/main/angular/src/app/location/detail/history/graph/simple-plot.component.html create mode 100644 src/main/angular/src/app/location/detail/history/graph/simple-plot.component.less create mode 100644 src/main/angular/src/app/location/detail/history/graph/simple-plot.component.ts create mode 100644 src/main/angular/src/app/point/PointResponse.ts create mode 100644 src/main/angular/src/app/point/PointSeries.ts create mode 100644 src/main/angular/src/app/point/point-service.ts delete mode 100644 src/main/angular/src/app/series/History.ts create mode 100644 src/main/angular/src/app/series/Interval.ts create mode 100644 src/main/java/de/ph87/data/point/IPointRequest.java create mode 100644 src/main/java/de/ph87/data/point/PointController.java create mode 100644 src/main/java/de/ph87/data/point/PointRequestRelative.java create mode 100644 src/main/java/de/ph87/data/point/PointResponse.java create mode 100644 src/main/java/de/ph87/data/point/PointSeries.java create mode 100644 src/main/java/de/ph87/data/point/PointService.java delete mode 100644 src/main/java/de/ph87/data/series/HistoryDto.java create mode 100644 src/main/java/de/ph87/data/series/data/delta/ISeriesPoint.java create mode 100644 src/main/java/de/ph87/data/series/data/delta/ISeriesPointSerializer.java delete mode 100644 src/main/java/de/ph87/data/series/point/AllSeriesPointRequest.java delete mode 100644 src/main/java/de/ph87/data/series/point/AllSeriesPointResponse.java delete mode 100644 src/main/java/de/ph87/data/series/point/ISeriesPointRequest.java delete mode 100644 src/main/java/de/ph87/data/series/point/OneSeriesPointsRequest.java delete mode 100644 src/main/java/de/ph87/data/series/point/OneSeriesPointsResponse.java delete mode 100644 src/main/java/de/ph87/data/series/point/OneSeriesPointsResponseSerializer.java delete mode 100644 src/main/java/de/ph87/data/series/point/SeriesPoint.java delete mode 100644 src/main/java/de/ph87/data/series/point/SeriesPointService.java diff --git a/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.html b/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.html new file mode 100644 index 0000000..7d4ce7e --- /dev/null +++ b/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.html @@ -0,0 +1,9 @@ +
+ @for (segment of segments; track segment) { +
+ + + +
+ } +
diff --git a/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.less b/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.less new file mode 100644 index 0000000..9474b56 --- /dev/null +++ b/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.less @@ -0,0 +1,9 @@ +.segments { + display: flex; + height: 4em; + + .segment { + flex: 1; + height: 100%; + } +} diff --git a/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.ts b/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.ts new file mode 100644 index 0000000..4e3e7db --- /dev/null +++ b/src/main/angular/src/app/location/detail/history/graph/simple-plot.component.ts @@ -0,0 +1,70 @@ +import {AfterViewInit, Component, Input} from '@angular/core'; +import {Location} from '../../../Location'; +import {Interval} from '../../../../series/Interval'; +import {PointService} from '../../../../point/point-service'; + +@Component({ + selector: 'app-series-history-graph', + imports: [], + templateUrl: './simple-plot.component.html', + styleUrl: './simple-plot.component.less', +}) +export class SeriesHistoryGraph implements AfterViewInit { + + protected segments = Array.from(Array(288).keys()); + + protected totals: number[] = []; + + protected historyEnergyPurchase: number[] | null = null; + + protected historyEnergyDeliver: number[] | null = null; + + protected historyEnergyProduce: number[] | null = null; + + protected readonly Interval = Interval; + + @Input() + heading!: string; + + @Input() + date!: Date; + + @Input() + interval!: Interval; + + @Input() + location!: Location; + + constructor( + readonly pointService: PointService, + ) { + // + } + + ngAfterViewInit(): void { + // this.history(this.location?.energyPurchase, history => this.historyEnergyPurchase = history); + // this.history(this.location?.energyDeliver, history => this.historyEnergyDeliver = history); + // this.history(this.location?.energyProduce, history => this.historyEnergyProduce = history); + } + + // public readonly updateSeries = (fresh: Series): void => { + // if (fresh.id === this.location?.energyPurchase?.id) { + // this.history(this.location?.energyPurchase, history => this.historyEnergyPurchase = history); + // } + // if (fresh.id === this.location?.energyDeliver?.id) { + // this.history(this.location?.energyDeliver, history => this.historyEnergyDeliver = history); + // } + // if (fresh.id === this.location?.energyProduce?.id) { + // this.history(this.location?.energyProduce, history => this.historyEnergyProduce = history); + // } + // }; + // + // private history(series: Series | null | undefined, next: Next) { + // if (!series || !this.interval) { + // next(null); + // return + // } + // this.pointService.points(series, this.date, this.interval, next); + // } + +} diff --git a/src/main/angular/src/app/location/detail/history/series-history.html b/src/main/angular/src/app/location/detail/history/series-history.html index 45cea1b..e0b29fb 100644 --- a/src/main/angular/src/app/location/detail/history/series-history.html +++ b/src/main/angular/src/app/location/detail/history/series-history.html @@ -30,4 +30,5 @@ + diff --git a/src/main/angular/src/app/location/detail/history/series-history.ts b/src/main/angular/src/app/location/detail/history/series-history.ts index a19d3bc..16d4cf0 100644 --- a/src/main/angular/src/app/location/detail/history/series-history.ts +++ b/src/main/angular/src/app/location/detail/history/series-history.ts @@ -1,23 +1,27 @@ import {AfterViewInit, Component, Input} from '@angular/core'; -import {History} from '../../../series/History'; import {Location} from '../../Location'; import {Series} from '../../../series/Series'; -import {Interval, SeriesService} from '../../../series/series-service'; import {Next} from '../../../common'; +import {SeriesHistoryGraph} from './graph/simple-plot.component'; +import {Interval} from '../../../series/Interval'; +import {PointService} from '../../../point/point-service'; +import {PointSeries} from '../../../point/PointSeries'; @Component({ selector: 'app-series-history', - imports: [], + imports: [ + SeriesHistoryGraph + ], templateUrl: './series-history.html', styleUrl: './series-history.less', }) export class SeriesHistory implements AfterViewInit { - protected historyEnergyPurchase: History | null = null; + protected historyEnergyPurchase: PointSeries | null = null; - protected historyEnergyDeliver: History | null = null; + protected historyEnergyDeliver: PointSeries | null = null; - protected historyEnergyProduce: History | null = null; + protected historyEnergyProduce: PointSeries | null = null; protected readonly Interval = Interval; @@ -25,7 +29,7 @@ export class SeriesHistory implements AfterViewInit { heading!: string; @Input() - date!: Date; + offset: number = 0; @Input() interval!: Interval; @@ -34,7 +38,7 @@ export class SeriesHistory implements AfterViewInit { location!: Location; constructor( - readonly seriesService: SeriesService, + readonly pointService: PointService, ) { // } @@ -57,12 +61,12 @@ export class SeriesHistory implements AfterViewInit { } }; - private history(series: Series | null | undefined, next: Next) { + private history(series: Series | null | undefined, next: Next) { if (!series || !this.interval) { next(null); return } - this.seriesService.history(series, this.date, this.interval, next); + this.pointService.relative([series], this.interval, this.offset, 1, response => next(response.series[0])); } } diff --git a/src/main/angular/src/app/location/detail/location-detail.html b/src/main/angular/src/app/location/detail/location-detail.html index d3cacd8..e572f18 100644 --- a/src/main/angular/src/app/location/detail/location-detail.html +++ b/src/main/angular/src/app/location/detail/location-detail.html @@ -1,8 +1,8 @@ @if (location) { - + - +
diff --git a/src/main/angular/src/app/location/detail/location-detail.ts b/src/main/angular/src/app/location/detail/location-detail.ts index 66ec39c..7e7d492 100644 --- a/src/main/angular/src/app/location/detail/location-detail.ts +++ b/src/main/angular/src/app/location/detail/location-detail.ts @@ -6,10 +6,11 @@ import {Text} from '../../shared/text/text'; import {Number} from '../../shared/number/number'; import {SeriesSelect} from '../../series/select/series-select'; import {Series} from '../../series/Series'; -import {Interval, SeriesService} from '../../series/series-service'; +import {SeriesService} from '../../series/series-service'; import {SeriesType} from '../../series/SeriesType'; import {Subscription, timer} from 'rxjs'; import {SeriesHistory} from './history/series-history'; +import {Interval} from '../../series/Interval'; function yesterday(now: any) { const yesterday = new Date(now.getTime()); diff --git a/src/main/angular/src/app/point/PointResponse.ts b/src/main/angular/src/app/point/PointResponse.ts new file mode 100644 index 0000000..4484c4e --- /dev/null +++ b/src/main/angular/src/app/point/PointResponse.ts @@ -0,0 +1,23 @@ +import {validateDate, validateList} from "../common"; + +import {PointSeries} from './PointSeries'; + +export class PointResponse { + + constructor( + readonly begin: Date, + readonly end: Date, + readonly series: PointSeries[], + ) { + // + } + + static fromJson(json: any): PointResponse { + return new PointResponse( + validateDate(json.begin), + validateDate(json.end), + validateList(json.series, PointSeries.fromJson), + ); + } + +} diff --git a/src/main/angular/src/app/point/PointSeries.ts b/src/main/angular/src/app/point/PointSeries.ts new file mode 100644 index 0000000..9d56fbe --- /dev/null +++ b/src/main/angular/src/app/point/PointSeries.ts @@ -0,0 +1,22 @@ +import {Series} from "../series/Series"; +import {validateList, validateNumber} from "../common"; + +export class PointSeries { + + readonly valueString: string; + + constructor( + readonly series: Series, + readonly points: number[][], + ) { + this.valueString = series.getValueString(points.length === 0 ? null : points[0][1]); + } + + static fromJson(json: any): PointSeries { + return new PointSeries( + Series.fromJson(json.series), + validateList(json.points, list => list.map(validateNumber)), + ); + } + +} diff --git a/src/main/angular/src/app/point/point-service.ts b/src/main/angular/src/app/point/point-service.ts new file mode 100644 index 0000000..b92e36c --- /dev/null +++ b/src/main/angular/src/app/point/point-service.ts @@ -0,0 +1,29 @@ +import {Injectable} from '@angular/core'; +import {ApiService, CrudService, Next, WebsocketService} from '../common'; +import {PointResponse} from './PointResponse'; +import {Series} from '../series/Series'; +import {Interval} from '../series/Interval'; + +@Injectable({ + providedIn: 'root' +}) +export class PointService extends CrudService { + + constructor( + api: ApiService, + ws: WebsocketService, + ) { + super(api, ws, ['Point'], PointResponse.fromJson); + } + + relative(series: Series[], interval: Interval, offset: number, count: number, next: Next): void { + const request = { + ids: series.map(s => s.id), + interval: interval, + offset: offset, + count: count, + }; + this.postSingle(['relative'], request, next); + } + +} diff --git a/src/main/angular/src/app/series/History.ts b/src/main/angular/src/app/series/History.ts deleted file mode 100644 index 5bd46a0..0000000 --- a/src/main/angular/src/app/series/History.ts +++ /dev/null @@ -1,22 +0,0 @@ -import {getValueString, Series} from "./Series"; -import {or, validateNumber} from "../common"; - -export class History { - - readonly valueString: string; - - constructor( - readonly series: Series, - readonly value: number | null, - ) { - this.valueString = getValueString(value, series); - } - - static fromJson(json: any): History { - return new History( - Series.fromJson(json.series), - or(json.value, validateNumber, null), - ); - } - -} diff --git a/src/main/angular/src/app/series/Interval.ts b/src/main/angular/src/app/series/Interval.ts new file mode 100644 index 0000000..c76cd5b --- /dev/null +++ b/src/main/angular/src/app/series/Interval.ts @@ -0,0 +1,8 @@ +export enum Interval { + FIVE = 'FIVE', + HOUR = 'HOUR', + DAY = 'DAY', + WEEK = 'WEEK', + MONTH = 'MONTH', + YEAR = 'YEAR', +} diff --git a/src/main/angular/src/app/series/Series.ts b/src/main/angular/src/app/series/Series.ts index 1020f3d..d96443f 100644 --- a/src/main/angular/src/app/series/Series.ts +++ b/src/main/angular/src/app/series/Series.ts @@ -3,10 +3,6 @@ import {or, validateDate, validateEnum, validateNumber, validateString} from ".. import {SeriesType} from './SeriesType'; import {formatNumber} from '@angular/common'; -export function getValueString(value: number | null, series: Series): string { - return (value === null ? '-' : formatNumber(value, "de-DE", `0.${series.decimals}-${series.decimals}`)) + ' ' + series.unit; -} - export class Series { readonly valueString: string; @@ -21,7 +17,11 @@ export class Series { readonly unit: string, readonly type: SeriesType, ) { - this.valueString = getValueString(value, this); + this.valueString = this.getValueString(value); + } + + getValueString(value: number | null | undefined): string { + return (value === null || value === undefined ? '-' : formatNumber(value, "de-DE", `0.${this.decimals}-${this.decimals}`)) + ' ' + this.unit; } static fromJson(json: any): Series { diff --git a/src/main/angular/src/app/series/series-service.ts b/src/main/angular/src/app/series/series-service.ts index 585acb7..33a8f66 100644 --- a/src/main/angular/src/app/series/series-service.ts +++ b/src/main/angular/src/app/series/series-service.ts @@ -1,18 +1,8 @@ import {Inject, Injectable, LOCALE_ID} from '@angular/core'; import {ApiService, CrudService, Next, WebsocketService} from '../common'; import {Series} from './Series'; -import {History} from './History'; import {DatePipe} from '@angular/common'; -export enum Interval { - FIVE = 'FIVE', - HOUR = 'HOUR', - DAY = 'DAY', - WEEK = 'WEEK', - MONTH = 'MONTH', - YEAR = 'YEAR', -} - @Injectable({ providedIn: 'root' }) @@ -33,8 +23,4 @@ export class SeriesService extends CrudService { this.getList(['findAll'], next); } - history(series: Series, date: Date, interval: Interval, next: Next) { - this.api.getSingle([...this.path, series.id, 'history', Math.floor(date.getTime() / 1000), interval], History.fromJson, next); - } - } diff --git a/src/main/angular/src/main.ts b/src/main/angular/src/main.ts index 5df75f9..9c2613b 100644 --- a/src/main/angular/src/main.ts +++ b/src/main/angular/src/main.ts @@ -1,6 +1,6 @@ -import { bootstrapApplication } from '@angular/platform-browser'; -import { appConfig } from './app/app.config'; -import { App } from './app/app'; +import {bootstrapApplication} from '@angular/platform-browser'; +import {appConfig} from './app/app.config'; +import {App} from './app/app'; bootstrapApplication(App, appConfig) .catch((err) => console.error(err)); diff --git a/src/main/java/de/ph87/data/DemoService.java b/src/main/java/de/ph87/data/DemoService.java index 50842e4..e0ed6ff 100644 --- a/src/main/java/de/ph87/data/DemoService.java +++ b/src/main/java/de/ph87/data/DemoService.java @@ -1,8 +1,8 @@ package de.ph87.data; import de.ph87.data.topic.TopicDto; -import de.ph87.data.topic.TopicType; import de.ph87.data.topic.TopicService; +import de.ph87.data.topic.TopicType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.event.ApplicationReadyEvent; diff --git a/src/main/java/de/ph87/data/plot/PlotDto.java b/src/main/java/de/ph87/data/plot/PlotDto.java index 9042e31..b89b834 100644 --- a/src/main/java/de/ph87/data/plot/PlotDto.java +++ b/src/main/java/de/ph87/data/plot/PlotDto.java @@ -15,8 +15,6 @@ public class PlotDto implements IWebsocketMessage { public final long version; - private final boolean deleted; - @NonNull public final String name; @@ -34,10 +32,9 @@ public class PlotDto implements IWebsocketMessage { @NonNull public final List axes; - public PlotDto(@NonNull final Plot plot, final boolean deleted) { + public PlotDto(@NonNull final Plot plot) { this.id = plot.getId(); this.version = plot.getVersion(); - this.deleted = deleted; this.name = plot.getName(); this.interval = plot.getInterval(); this.offset = plot.getOffset(); diff --git a/src/main/java/de/ph87/data/plot/PlotRepository.java b/src/main/java/de/ph87/data/plot/PlotRepository.java index 1eb5492..cd5f403 100644 --- a/src/main/java/de/ph87/data/plot/PlotRepository.java +++ b/src/main/java/de/ph87/data/plot/PlotRepository.java @@ -8,7 +8,7 @@ import java.util.Optional; public interface PlotRepository extends ListCrudRepository { - @Query("select new de.ph87.data.plot.PlotDto(p, false) from Plot p") + @Query("select new de.ph87.data.plot.PlotDto(p) from Plot p") List findAllDto(); @Query("select max(p.position) from Plot p") diff --git a/src/main/java/de/ph87/data/plot/PlotService.java b/src/main/java/de/ph87/data/plot/PlotService.java index ed03287..20d000d 100644 --- a/src/main/java/de/ph87/data/plot/PlotService.java +++ b/src/main/java/de/ph87/data/plot/PlotService.java @@ -87,7 +87,7 @@ public class PlotService { } else { log.info("Updated: plot={}", plot); } - final PlotDto dto = new PlotDto(plot, deleted); + final PlotDto dto = new PlotDto(plot); applicationEventPublisher.publishEvent(dto); return dto; } diff --git a/src/main/java/de/ph87/data/plot/axis/graph/GraphDto.java b/src/main/java/de/ph87/data/plot/axis/graph/GraphDto.java index 1a0e588..970f8f2 100644 --- a/src/main/java/de/ph87/data/plot/axis/graph/GraphDto.java +++ b/src/main/java/de/ph87/data/plot/axis/graph/GraphDto.java @@ -14,7 +14,7 @@ public class GraphDto { public final long version; - @NonNull + @Nullable public final SeriesDto series; public final double factor; @@ -53,10 +53,10 @@ public class GraphDto { public GraphDto(@NonNull final Graph graph) { this.id = graph.getId(); this.version = graph.getVersion(); - this.series = new SeriesDto(graph.getSeries()); + this.series = map(graph.getSeries(), SeriesDto::new); this.factor = graph.getFactor(); this.operation = graph.getOperation(); - this.series2 = map(graph.getSeries2(), false, SeriesDto::new); + this.series2 = map(graph.getSeries2(), SeriesDto::new); this.factor2 = graph.getFactor2(); this.name = graph.getName(); this.visible = graph.isVisible(); diff --git a/src/main/java/de/ph87/data/point/IPointRequest.java b/src/main/java/de/ph87/data/point/IPointRequest.java new file mode 100644 index 0000000..4aa19eb --- /dev/null +++ b/src/main/java/de/ph87/data/point/IPointRequest.java @@ -0,0 +1,27 @@ +package de.ph87.data.point; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import de.ph87.data.series.data.Interval; +import lombok.NonNull; + +import java.time.ZonedDateTime; +import java.util.List; + +@JsonSubTypes({ + @JsonSubTypes.Type(PointRequestRelative.class), +}) +public interface IPointRequest { + + @NonNull + List getIds(); + + @NonNull + Interval getInterval(); + + @NonNull + ZonedDateTime getBegin(); + + @NonNull + ZonedDateTime getEnd(); + +} diff --git a/src/main/java/de/ph87/data/point/PointController.java b/src/main/java/de/ph87/data/point/PointController.java new file mode 100644 index 0000000..60d3cae --- /dev/null +++ b/src/main/java/de/ph87/data/point/PointController.java @@ -0,0 +1,23 @@ +package de.ph87.data.point; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@CrossOrigin +@RestController +@RequiredArgsConstructor +@RequestMapping("Point") +public class PointController { + + private final PointService pointService; + + @PostMapping("relative") + public PointResponse points(@RequestBody final PointRequestRelative request) { + return pointService.points(request); + } + +} diff --git a/src/main/java/de/ph87/data/point/PointRequestRelative.java b/src/main/java/de/ph87/data/point/PointRequestRelative.java new file mode 100644 index 0000000..a3c2def --- /dev/null +++ b/src/main/java/de/ph87/data/point/PointRequestRelative.java @@ -0,0 +1,38 @@ +package de.ph87.data.point; + +import de.ph87.data.series.data.Interval; +import lombok.Data; + +import java.time.ZonedDateTime; +import java.util.List; + +@Data +public class PointRequestRelative implements IPointRequest { + + public final List ids; + + public final Interval interval; + + public final long offset; + + public final long count; + + public final ZonedDateTime begin; + + public final ZonedDateTime end; + + public PointRequestRelative( + final List ids, + final Interval interval, + final long offset, + final long count + ) { + this.ids = ids; + this.interval = interval; + this.offset = offset; + this.count = count; + this.end = interval.align.apply(ZonedDateTime.now()).minus(interval.amount * (offset - 1), interval.unit); + this.begin = this.end.minus(interval.amount * count, interval.unit); + } + +} diff --git a/src/main/java/de/ph87/data/point/PointResponse.java b/src/main/java/de/ph87/data/point/PointResponse.java new file mode 100644 index 0000000..91f6c47 --- /dev/null +++ b/src/main/java/de/ph87/data/point/PointResponse.java @@ -0,0 +1,17 @@ +package de.ph87.data.point; + +import lombok.Data; + +import java.time.ZonedDateTime; +import java.util.List; + +@Data +public class PointResponse { + + public final ZonedDateTime begin; + + public final ZonedDateTime end; + + public final List series; + +} diff --git a/src/main/java/de/ph87/data/point/PointSeries.java b/src/main/java/de/ph87/data/point/PointSeries.java new file mode 100644 index 0000000..f9ffaa3 --- /dev/null +++ b/src/main/java/de/ph87/data/point/PointSeries.java @@ -0,0 +1,16 @@ +package de.ph87.data.point; + +import de.ph87.data.series.SeriesDto; +import de.ph87.data.series.data.delta.ISeriesPoint; +import lombok.Data; + +import java.util.List; + +@Data +public class PointSeries { + + public final SeriesDto series; + + public final List points; + +} diff --git a/src/main/java/de/ph87/data/point/PointService.java b/src/main/java/de/ph87/data/point/PointService.java new file mode 100644 index 0000000..1092c70 --- /dev/null +++ b/src/main/java/de/ph87/data/point/PointService.java @@ -0,0 +1,47 @@ +package de.ph87.data.point; + +import de.ph87.data.series.Series; +import de.ph87.data.series.SeriesDto; +import de.ph87.data.series.SeriesService; +import de.ph87.data.series.data.bool.BoolService; +import de.ph87.data.series.data.delta.DeltaService; +import de.ph87.data.series.data.delta.ISeriesPoint; +import de.ph87.data.series.data.varying.VaryingService; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class PointService { + + private final SeriesService seriesService; + + private final BoolService boolService; + + private final DeltaService deltaService; + + private final VaryingService varyingService; + + @NonNull + public PointResponse points(@NonNull final IPointRequest request) { + final List series = request.getIds().stream().map(s -> points(s, request)).toList(); + return new PointResponse(request.getBegin(), request.getEnd(), series); + } + + @NonNull + private PointSeries points(final long id, @NonNull final IPointRequest request) { + final Series series = seriesService.getById(id); + final List points = switch (series.getType()) { + case BOOL -> boolService.points(series, request); + case DELTA -> deltaService.points(series, request); + case VARYING -> varyingService.points(series, request); + }; + return new PointSeries(new SeriesDto(series), points); + } + +} diff --git a/src/main/java/de/ph87/data/series/HistoryDto.java b/src/main/java/de/ph87/data/series/HistoryDto.java deleted file mode 100644 index 6af0a8e..0000000 --- a/src/main/java/de/ph87/data/series/HistoryDto.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.ph87.data.series; - -import de.ph87.data.series.point.AllSeriesPointResponse; -import jakarta.annotation.Nullable; -import lombok.Data; -import lombok.NonNull; - -@Data -public class HistoryDto { - - @NonNull - public final SeriesDto series; - - @Nullable - public final Double value; - - public HistoryDto(final AllSeriesPointResponse.Entry entry) { - this.series = entry.getSeries(); - this.value = entry.point == null ? null : entry.point.getValue(); - } - -} diff --git a/src/main/java/de/ph87/data/series/SeriesController.java b/src/main/java/de/ph87/data/series/SeriesController.java index 269324b..6a49ee9 100644 --- a/src/main/java/de/ph87/data/series/SeriesController.java +++ b/src/main/java/de/ph87/data/series/SeriesController.java @@ -1,11 +1,5 @@ package de.ph87.data.series; -import de.ph87.data.series.data.Interval; -import de.ph87.data.series.point.AllSeriesPointRequest; -import de.ph87.data.series.point.AllSeriesPointResponse; -import de.ph87.data.series.point.OneSeriesPointsRequest; -import de.ph87.data.series.point.OneSeriesPointsResponse; -import de.ph87.data.series.point.SeriesPointService; import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.CrossOrigin; @@ -16,9 +10,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; import java.util.List; @CrossOrigin @@ -31,8 +22,6 @@ public class SeriesController { private final SeriesService seriesService; - private final SeriesPointService seriesPointService; - @GetMapping("create") public SeriesDto create() { return seriesService.create(); @@ -68,13 +57,6 @@ public class SeriesController { return seriesService.modify(id, series -> series.setType(type)); } - @NonNull - @GetMapping("{id}/history/{epochSeconds}/{intervalName}") - public HistoryDto type(@PathVariable final long id, @PathVariable @NonNull final long epochSeconds, @PathVariable @NonNull final String intervalName) { - final Interval interval = Interval.valueOf(intervalName); - return seriesPointService.history(id, ZonedDateTime.ofInstant(Instant.ofEpochSecond(epochSeconds), ZoneId.systemDefault()), interval); - } - @NonNull @GetMapping("{id}") public SeriesDto getById(@PathVariable final long id) { @@ -87,16 +69,4 @@ public class SeriesController { return seriesRepository.findAllDto(); } - @NonNull - @PostMapping("oneSeriesPoints") - public OneSeriesPointsResponse oneSeriesPoints(@NonNull @RequestBody final OneSeriesPointsRequest request) { - return seriesPointService.oneSeriesPoints(request); - } - - @NonNull - @PostMapping("allSeriesPoint") - public AllSeriesPointResponse allSeriesPoint(@NonNull @RequestBody final AllSeriesPointRequest request) { - return seriesPointService.allSeriesPoint(request); - } - } diff --git a/src/main/java/de/ph87/data/series/SeriesDto.java b/src/main/java/de/ph87/data/series/SeriesDto.java index 33edc35..c38de70 100644 --- a/src/main/java/de/ph87/data/series/SeriesDto.java +++ b/src/main/java/de/ph87/data/series/SeriesDto.java @@ -14,8 +14,6 @@ public class SeriesDto implements IWebsocketMessage { public final long version; - public final boolean deleted; - public final String name; @NonNull @@ -38,13 +36,8 @@ public class SeriesDto implements IWebsocketMessage { public final SeriesType type; public SeriesDto(@NonNull final Series series) { - this(series, false); - } - - public SeriesDto(@NonNull final Series series, final boolean deleted) { this.id = series.getId(); this.version = series.getVersion(); - this.deleted = deleted; this.name = series.getName(); this.unit = series.getUnit(); this.decimals = series.getDecimals(); diff --git a/src/main/java/de/ph87/data/series/SeriesRepository.java b/src/main/java/de/ph87/data/series/SeriesRepository.java index b6c9450..6a0cd4c 100644 --- a/src/main/java/de/ph87/data/series/SeriesRepository.java +++ b/src/main/java/de/ph87/data/series/SeriesRepository.java @@ -5,23 +5,17 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.ListCrudRepository; import java.util.List; -import java.util.Optional; public interface SeriesRepository extends ListCrudRepository { @NonNull - Optional findByName(@NonNull String seriesName); - - @NonNull - @Query("select new de.ph87.data.series.SeriesDto(s, false) from Series s where s.id = :id") + @Query("select new de.ph87.data.series.SeriesDto(s) from Series s where s.id = :id") SeriesDto getDtoById(long id); @NonNull - @Query("select new de.ph87.data.series.SeriesDto(t, false) from Series t") + @Query("select new de.ph87.data.series.SeriesDto(t) from Series t") List findAllDto(); - Optional findFirstByOrderByNameAsc(); - boolean existsByName(@NonNull String name); } diff --git a/src/main/java/de/ph87/data/series/data/bool/Bool.java b/src/main/java/de/ph87/data/series/data/bool/Bool.java index 484ae97..e1d0490 100644 --- a/src/main/java/de/ph87/data/series/data/bool/Bool.java +++ b/src/main/java/de/ph87/data/series/data/bool/Bool.java @@ -32,15 +32,15 @@ public class Bool { @Setter @NonNull @Column(nullable = false, name = "`end`") - private ZonedDateTime end; + private ZonedDateTime since; @Setter @Column(nullable = false) private boolean terminated; - public Bool(@NonNull final DataId id, @NonNull final ZonedDateTime end, final boolean state, final boolean terminated) { + public Bool(@NonNull final DataId id, @NonNull final ZonedDateTime since, final boolean state, final boolean terminated) { this.id = id; - this.end = end; + this.since = since; this.state = state; this.terminated = terminated; } diff --git a/src/main/java/de/ph87/data/series/data/bool/BoolDto.java b/src/main/java/de/ph87/data/series/data/bool/BoolDto.java index 069fa6a..331af3d 100644 --- a/src/main/java/de/ph87/data/series/data/bool/BoolDto.java +++ b/src/main/java/de/ph87/data/series/data/bool/BoolDto.java @@ -27,7 +27,7 @@ public class BoolDto implements IWebsocketMessage { public BoolDto(@NonNull final Bool bool) { this.series = new SeriesDto(bool.getId().getSeries()); this.date = bool.getId().getDate(); - this.end = bool.getEnd(); + this.end = bool.getSince(); this.state = bool.isState(); this.terminated = bool.isTerminated(); } diff --git a/src/main/java/de/ph87/data/series/data/bool/BoolPoint.java b/src/main/java/de/ph87/data/series/data/bool/BoolPoint.java index 94e5df6..9374676 100644 --- a/src/main/java/de/ph87/data/series/data/bool/BoolPoint.java +++ b/src/main/java/de/ph87/data/series/data/bool/BoolPoint.java @@ -1,65 +1,34 @@ package de.ph87.data.series.data.bool; -import de.ph87.data.plot.axis.graph.GraphDivisionByZero; -import de.ph87.data.plot.axis.graph.GraphOperation; -import de.ph87.data.series.point.SeriesPoint; +import de.ph87.data.series.data.delta.ISeriesPoint; import lombok.Data; import lombok.NonNull; -import tools.jackson.core.JsonGenerator; import java.time.ZonedDateTime; +import java.util.List; @Data -public class BoolPoint implements SeriesPoint { +public class BoolPoint implements ISeriesPoint { - public final ZonedDateTime begin; + public final ZonedDateTime date; - public final ZonedDateTime end; + public final ZonedDateTime since; public final boolean state; public final boolean terminated; public BoolPoint(@NonNull final Bool bool) { - this.begin = bool.getId().getDate(); - this.end = bool.getEnd(); + this.date = bool.getId().getDate(); + this.since = bool.getSince(); this.state = bool.isState(); this.terminated = bool.isTerminated(); } - public BoolPoint(final ZonedDateTime begin, final ZonedDateTime end, final boolean state, final boolean terminated) { - this.begin = begin; - this.end = end; - this.state = state; - this.terminated = terminated; - } - + @NonNull @Override - public void toJson(final JsonGenerator jsonGenerator) { - jsonGenerator.writeNumber(begin.toEpochSecond()); - jsonGenerator.writeNumber(end.toEpochSecond()); - jsonGenerator.writeNumber(state ? 1 : 0); - jsonGenerator.writeNumber(terminated ? 1 : 0); - } - - @Override - public BoolPoint times(final double factor) { - return this; - } - - @Override - public ZonedDateTime getDate() { - return begin; - } - - @Override - public double getValue() { - return state ? 1 : 0; - } - - @Override - public BoolPoint combine(@NonNull final SeriesPoint other, @NonNull final GraphOperation operation) throws GraphDivisionByZero { - return new BoolPoint(begin, end, operation.apply(getValue(), other.getValue()) > 0, terminated); + public List getValues() { + return List.of(state ? 1.0 : 0.0); } } diff --git a/src/main/java/de/ph87/data/series/data/bool/BoolRepo.java b/src/main/java/de/ph87/data/series/data/bool/BoolRepo.java index 00bcf90..8f5b79a 100644 --- a/src/main/java/de/ph87/data/series/data/bool/BoolRepo.java +++ b/src/main/java/de/ph87/data/series/data/bool/BoolRepo.java @@ -12,7 +12,7 @@ import java.util.List; public interface BoolRepo extends CrudRepository { @NonNull - @Query("select new de.ph87.data.series.data.bool.BoolPoint(e) from Bool e where e.id.series = :series and e.end >= :first and e.id.date < :after") - List points(@NonNull Series series, @NonNull ZonedDateTime first, @NonNull ZonedDateTime after); + @Query("select new de.ph87.data.series.data.bool.BoolPoint(e) from Bool e where e.id.series = :series and e.since >= :begin and e.id.date < :end") + List points(@NonNull Series series, @NonNull ZonedDateTime begin, @NonNull ZonedDateTime end); } diff --git a/src/main/java/de/ph87/data/series/data/bool/BoolService.java b/src/main/java/de/ph87/data/series/data/bool/BoolService.java index d49d2fa..c4b73ab 100644 --- a/src/main/java/de/ph87/data/series/data/bool/BoolService.java +++ b/src/main/java/de/ph87/data/series/data/bool/BoolService.java @@ -1,9 +1,9 @@ package de.ph87.data.series.data.bool; +import de.ph87.data.point.IPointRequest; import de.ph87.data.series.Series; import de.ph87.data.series.SeriesService; import de.ph87.data.series.data.DataId; -import de.ph87.data.series.point.ISeriesPointRequest; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -12,6 +12,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.ZonedDateTime; +import java.util.Collections; import java.util.List; @Slf4j @@ -42,22 +43,24 @@ public class BoolService { log.error("Differing states: received=(begin={}, end={}, state={}, terminated={}), existing={}", begin, end, state, terminated, existing); return; } - if (existing.getEnd().isAfter(end)) { + if (existing.getSince().isAfter(end)) { log.error("End ran backwards: received=(begin={}, end={}, state={}, terminated={}), existing={}", begin, end, state, terminated, existing); return; } - if (existing.isTerminated() && (!terminated || !existing.getEnd().equals(end))) { + if (existing.isTerminated() && (!terminated || !existing.getSince().equals(end))) { log.error("Already terminated: received=(begin={}, end={}, state={}, terminated={}), existing={}", begin, end, state, terminated, existing); return; } - existing.setEnd(end); + existing.setSince(end); existing.setTerminated(terminated); }).findFirst().orElseGet(() -> boolRepo.save(new Bool(id, end, state, terminated))); } @NonNull - public List points(@NonNull final Series series, @NonNull final ISeriesPointRequest request) { - return boolRepo.points(series, request.getFirst(), request.getAfter()); + @SuppressWarnings("unused") + public List points(@NonNull final Series series, @NonNull final IPointRequest request) { + log.warn("BoolService.points(...) Not implemented yet!"); + return Collections.emptyList(); // TODO } } diff --git a/src/main/java/de/ph87/data/series/data/delta/DeltaPoint.java b/src/main/java/de/ph87/data/series/data/delta/DeltaPoint.java index d2cc331..ef7b61e 100644 --- a/src/main/java/de/ph87/data/series/data/delta/DeltaPoint.java +++ b/src/main/java/de/ph87/data/series/data/delta/DeltaPoint.java @@ -1,16 +1,13 @@ package de.ph87.data.series.data.delta; -import de.ph87.data.plot.axis.graph.GraphDivisionByZero; -import de.ph87.data.plot.axis.graph.GraphOperation; -import de.ph87.data.series.point.SeriesPoint; import lombok.Data; import lombok.NonNull; -import tools.jackson.core.JsonGenerator; import java.time.ZonedDateTime; +import java.util.List; @Data -public class DeltaPoint implements SeriesPoint { +public class DeltaPoint implements ISeriesPoint { @NonNull public final ZonedDateTime date; @@ -22,25 +19,10 @@ public class DeltaPoint implements SeriesPoint { this.delta = delta; } + @NonNull @Override - public void toJson(final JsonGenerator jsonGenerator) { - jsonGenerator.writeNumber(date.toEpochSecond()); - jsonGenerator.writeNumber(delta); - } - - @Override - public DeltaPoint times(final double factor) { - return new DeltaPoint(date, delta * factor); - } - - @Override - public double getValue() { - return delta; - } - - @Override - public DeltaPoint combine(@NonNull final SeriesPoint other, @NonNull final GraphOperation operation) throws GraphDivisionByZero { - return new DeltaPoint(date, operation.apply(getValue(), other.getValue())); + public List getValues() { + return List.of(delta); } } diff --git a/src/main/java/de/ph87/data/series/data/delta/DeltaRepo.java b/src/main/java/de/ph87/data/series/data/delta/DeltaRepo.java index acb2898..183152d 100644 --- a/src/main/java/de/ph87/data/series/data/delta/DeltaRepo.java +++ b/src/main/java/de/ph87/data/series/data/delta/DeltaRepo.java @@ -13,7 +13,7 @@ import java.util.List; public interface DeltaRepo extends CrudRepository { @NonNull - @Query("select new de.ph87.data.series.data.delta.DeltaPoint(e.id.date, sum((e.last - e.first))) from #{#entityName} e where e.id.meter.series = :series and e.id.date >= :first and e.id.date < :after group by e.id.date") - List points(@NonNull Series series, @NonNull ZonedDateTime first, @NonNull ZonedDateTime after); + @Query("select new de.ph87.data.series.data.delta.DeltaPoint(e.id.date, sum((e.last - e.first))) from #{#entityName} e where e.id.meter.series = :series and e.id.date >= :begin and e.id.date < :end group by e.id.date") + List points(@NonNull Series series, @NonNull ZonedDateTime begin, @NonNull ZonedDateTime end); } diff --git a/src/main/java/de/ph87/data/series/data/delta/DeltaService.java b/src/main/java/de/ph87/data/series/data/delta/DeltaService.java index 02fc31a..4ec4fc0 100644 --- a/src/main/java/de/ph87/data/series/data/delta/DeltaService.java +++ b/src/main/java/de/ph87/data/series/data/delta/DeltaService.java @@ -1,11 +1,11 @@ package de.ph87.data.series.data.delta; +import de.ph87.data.point.IPointRequest; import de.ph87.data.series.Series; import de.ph87.data.series.SeriesService; import de.ph87.data.series.data.Interval; import de.ph87.data.series.data.delta.meter.Meter; import de.ph87.data.series.data.delta.meter.MeterRepository; -import de.ph87.data.series.point.ISeriesPointRequest; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -72,14 +72,14 @@ public class DeltaService { } @NonNull - public List points(@NonNull final Series series, @NonNull final ISeriesPointRequest request) { + public List points(@NonNull final Series series, @NonNull final IPointRequest request) { return switch (request.getInterval()) { - case FIVE -> five.points(series, request.getFirst(), request.getAfter()); - case HOUR -> hour.points(series, request.getFirst(), request.getAfter()); - case DAY -> day.points(series, request.getFirst(), request.getAfter()); - case WEEK -> week.points(series, request.getFirst(), request.getAfter()); - case MONTH -> month.points(series, request.getFirst(), request.getAfter()); - case YEAR -> year.points(series, request.getFirst(), request.getAfter()); + case FIVE -> five.points(series, request.getBegin(), request.getEnd()); + case HOUR -> hour.points(series, request.getBegin(), request.getEnd()); + case DAY -> day.points(series, request.getBegin(), request.getEnd()); + case WEEK -> week.points(series, request.getBegin(), request.getEnd()); + case MONTH -> month.points(series, request.getBegin(), request.getEnd()); + case YEAR -> year.points(series, request.getBegin(), request.getEnd()); }; } diff --git a/src/main/java/de/ph87/data/series/data/delta/ISeriesPoint.java b/src/main/java/de/ph87/data/series/data/delta/ISeriesPoint.java new file mode 100644 index 0000000..50f824a --- /dev/null +++ b/src/main/java/de/ph87/data/series/data/delta/ISeriesPoint.java @@ -0,0 +1,18 @@ +package de.ph87.data.series.data.delta; + +import lombok.NonNull; +import tools.jackson.databind.annotation.JsonSerialize; + +import java.time.ZonedDateTime; +import java.util.List; + +@JsonSerialize(using = ISeriesPointSerializer.class) +public interface ISeriesPoint { + + @NonNull + ZonedDateTime getDate(); + + @NonNull + List getValues(); + +} diff --git a/src/main/java/de/ph87/data/series/data/delta/ISeriesPointSerializer.java b/src/main/java/de/ph87/data/series/data/delta/ISeriesPointSerializer.java new file mode 100644 index 0000000..2a4aa00 --- /dev/null +++ b/src/main/java/de/ph87/data/series/data/delta/ISeriesPointSerializer.java @@ -0,0 +1,20 @@ +package de.ph87.data.series.data.delta; + +import tools.jackson.core.JacksonException; +import tools.jackson.core.JsonGenerator; +import tools.jackson.databind.SerializationContext; +import tools.jackson.databind.ValueSerializer; + +public class ISeriesPointSerializer extends ValueSerializer { + + @Override + public void serialize(final ISeriesPoint value, final JsonGenerator gen, final SerializationContext ctxt) throws JacksonException { + gen.writeStartArray(); + gen.writeNumber(value.getDate().toEpochSecond()); + for (double v : value.getValues()) { + gen.writeNumber(v); + } + gen.writeEndArray(); + } + +} diff --git a/src/main/java/de/ph87/data/series/data/varying/VaryingPoint.java b/src/main/java/de/ph87/data/series/data/varying/VaryingPoint.java index 90978a4..483a412 100644 --- a/src/main/java/de/ph87/data/series/data/varying/VaryingPoint.java +++ b/src/main/java/de/ph87/data/series/data/varying/VaryingPoint.java @@ -1,16 +1,14 @@ package de.ph87.data.series.data.varying; -import de.ph87.data.plot.axis.graph.GraphDivisionByZero; -import de.ph87.data.plot.axis.graph.GraphOperation; -import de.ph87.data.series.point.SeriesPoint; +import de.ph87.data.series.data.delta.ISeriesPoint; import lombok.Data; import lombok.NonNull; -import tools.jackson.core.JsonGenerator; import java.time.ZonedDateTime; +import java.util.List; @Data -public class VaryingPoint implements SeriesPoint { +public class VaryingPoint implements ISeriesPoint { public final ZonedDateTime date; @@ -27,37 +25,10 @@ public class VaryingPoint implements SeriesPoint { this.avg = varying.getAvg(); } - private VaryingPoint(final ZonedDateTime date, final double min, final double avg, final double max) { - this.date = date; - this.min = min; - this.avg = avg; - this.max = max; - } - + @NonNull @Override - public void toJson(final JsonGenerator jsonGenerator) { - jsonGenerator.writeNumber(date.toEpochSecond()); - jsonGenerator.writeNumber(min); - jsonGenerator.writeNumber(max); - jsonGenerator.writeNumber(avg); - } - - @Override - public VaryingPoint times(final double factor) { - return new VaryingPoint(date, min * factor, avg * factor, max * factor); - } - - @Override - public double getValue() { - return avg; - } - - @Override - public VaryingPoint combine(@NonNull final SeriesPoint other, @NonNull final GraphOperation operation) throws GraphDivisionByZero { - if (other instanceof final VaryingPoint otherVarying) { - return new VaryingPoint(date, operation.apply(min, otherVarying.min), operation.apply(avg, otherVarying.avg), operation.apply(max, otherVarying.max)); - } - return new VaryingPoint(date, operation.apply(min, other.getValue()), operation.apply(avg, other.getValue()), operation.apply(max, other.getValue())); + public List getValues() { + return List.of(avg, min, max); } } diff --git a/src/main/java/de/ph87/data/series/data/varying/VaryingRepo.java b/src/main/java/de/ph87/data/series/data/varying/VaryingRepo.java index fa8a70b..fa6229e 100644 --- a/src/main/java/de/ph87/data/series/data/varying/VaryingRepo.java +++ b/src/main/java/de/ph87/data/series/data/varying/VaryingRepo.java @@ -14,7 +14,7 @@ import java.util.List; public interface VaryingRepo extends CrudRepository { @NonNull - @Query("select new de.ph87.data.series.data.varying.VaryingPoint(e) from #{#entityName} e where e.id.series = :series and e.id.date >= :first and e.id.date < :after") - List points(@NonNull Series series, @NonNull ZonedDateTime first, @NonNull ZonedDateTime after); + @Query("select new de.ph87.data.series.data.varying.VaryingPoint(e) from #{#entityName} e where e.id.series = :series and e.id.date >= :begin and e.id.date < :end") + List points(@NonNull Series series, @NonNull ZonedDateTime begin, @NonNull ZonedDateTime end); } diff --git a/src/main/java/de/ph87/data/series/data/varying/VaryingService.java b/src/main/java/de/ph87/data/series/data/varying/VaryingService.java index 2751685..2bab21f 100644 --- a/src/main/java/de/ph87/data/series/data/varying/VaryingService.java +++ b/src/main/java/de/ph87/data/series/data/varying/VaryingService.java @@ -1,10 +1,10 @@ package de.ph87.data.series.data.varying; +import de.ph87.data.point.IPointRequest; import de.ph87.data.series.Series; import de.ph87.data.series.SeriesService; import de.ph87.data.series.data.DataId; import de.ph87.data.series.data.Interval; -import de.ph87.data.series.point.ISeriesPointRequest; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -56,14 +56,14 @@ public class VaryingService { } @NonNull - public List points(@NonNull final Series series, @NonNull final ISeriesPointRequest request) { + public List points(@NonNull final Series series, @NonNull final IPointRequest request) { return switch (request.getInterval()) { - case FIVE -> five.points(series, request.getFirst(), request.getAfter()); - case HOUR -> hour.points(series, request.getFirst(), request.getAfter()); - case DAY -> day.points(series, request.getFirst(), request.getAfter()); - case WEEK -> week.points(series, request.getFirst(), request.getAfter()); - case MONTH -> month.points(series, request.getFirst(), request.getAfter()); - case YEAR -> year.points(series, request.getFirst(), request.getAfter()); + case FIVE -> five.points(series, request.getBegin(), request.getEnd()); + case HOUR -> hour.points(series, request.getBegin(), request.getEnd()); + case DAY -> day.points(series, request.getBegin(), request.getEnd()); + case WEEK -> week.points(series, request.getBegin(), request.getEnd()); + case MONTH -> month.points(series, request.getBegin(), request.getEnd()); + case YEAR -> year.points(series, request.getBegin(), request.getEnd()); }; } diff --git a/src/main/java/de/ph87/data/series/point/AllSeriesPointRequest.java b/src/main/java/de/ph87/data/series/point/AllSeriesPointRequest.java deleted file mode 100644 index d59e7f3..0000000 --- a/src/main/java/de/ph87/data/series/point/AllSeriesPointRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -package de.ph87.data.series.point; - -import com.fasterxml.jackson.annotation.JsonProperty; -import de.ph87.data.series.data.Interval; -import lombok.Data; -import lombok.NonNull; - -import java.time.ZonedDateTime; - -@Data -public class AllSeriesPointRequest implements ISeriesPointRequest { - - @NonNull - public final Interval interval; - - public final long offset; - - @NonNull - public final ZonedDateTime first; - - @NonNull - public final ZonedDateTime after; - - public AllSeriesPointRequest( - @JsonProperty("interval") final Interval interval, - @JsonProperty("offset") final long offset - ) { - this.interval = interval; - this.offset = offset; - this.first = interval.align.apply(ZonedDateTime.now()).minus(interval.amount * offset, interval.unit); - this.after = this.first.plus(interval.amount, interval.unit); - } - -} diff --git a/src/main/java/de/ph87/data/series/point/AllSeriesPointResponse.java b/src/main/java/de/ph87/data/series/point/AllSeriesPointResponse.java deleted file mode 100644 index 72aec2b..0000000 --- a/src/main/java/de/ph87/data/series/point/AllSeriesPointResponse.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.ph87.data.series.point; - -import de.ph87.data.series.SeriesDto; -import jakarta.annotation.Nullable; -import lombok.Data; -import lombok.NonNull; - -import java.util.List; - -@Data -public class AllSeriesPointResponse { - - @NonNull - public final AllSeriesPointRequest request; - - @NonNull - public final List seriesPoints; - - @Data - public static class Entry { - - @NonNull - public final SeriesDto series; - - @Nullable - public final SeriesPoint point; - - } - -} diff --git a/src/main/java/de/ph87/data/series/point/ISeriesPointRequest.java b/src/main/java/de/ph87/data/series/point/ISeriesPointRequest.java deleted file mode 100644 index 7da4fcd..0000000 --- a/src/main/java/de/ph87/data/series/point/ISeriesPointRequest.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.ph87.data.series.point; - -import de.ph87.data.series.data.Interval; -import lombok.NonNull; - -import java.time.ZonedDateTime; - -public interface ISeriesPointRequest { - - @NonNull - Interval getInterval(); - - @NonNull - ZonedDateTime getFirst(); - - @NonNull - ZonedDateTime getAfter(); - -} diff --git a/src/main/java/de/ph87/data/series/point/OneSeriesPointsRequest.java b/src/main/java/de/ph87/data/series/point/OneSeriesPointsRequest.java deleted file mode 100644 index 0c1971e..0000000 --- a/src/main/java/de/ph87/data/series/point/OneSeriesPointsRequest.java +++ /dev/null @@ -1,64 +0,0 @@ -package de.ph87.data.series.point; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; -import de.ph87.data.plot.axis.graph.GraphOperation; -import de.ph87.data.series.data.Interval; -import jakarta.annotation.Nullable; -import lombok.Data; -import lombok.NonNull; - -import java.time.ZonedDateTime; - -@Data -public class OneSeriesPointsRequest implements ISeriesPointRequest { - - public final long id; - - public final double factor; - - public final GraphOperation operation; - - @Nullable - public final Long id2; - - public final double factor2; - - @NonNull - public final Interval interval; - - public final long offset; - - public final long duration; - - @NonNull - @JsonIgnore - public final ZonedDateTime first; - - @NonNull - @JsonIgnore - public final ZonedDateTime after; - - public OneSeriesPointsRequest( - @JsonProperty("id") final long id, - @JsonProperty("factor") final double factor, - @JsonProperty("operation") final GraphOperation operation, - @JsonProperty("id2") @Nullable final Long id2, - @JsonProperty("factor2") final double factor2, - @JsonProperty("interval") final Interval interval, - @JsonProperty("offset") final long offset, - @JsonProperty("duration") final long duration - ) { - this.id = id; - this.factor = factor; - this.operation = operation; - this.id2 = id2; - this.factor2 = factor2; - this.interval = interval; - this.offset = offset; - this.duration = duration; - this.after = interval.align.apply(ZonedDateTime.now()).minus(interval.amount * (offset - 1), interval.unit); - this.first = this.after.minus(interval.amount * duration, interval.unit); - } - -} diff --git a/src/main/java/de/ph87/data/series/point/OneSeriesPointsResponse.java b/src/main/java/de/ph87/data/series/point/OneSeriesPointsResponse.java deleted file mode 100644 index 9249188..0000000 --- a/src/main/java/de/ph87/data/series/point/OneSeriesPointsResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package de.ph87.data.series.point; - -import tools.jackson.databind.annotation.JsonSerialize; -import lombok.Data; - -import java.util.List; - -@Data -@JsonSerialize(using = OneSeriesPointsResponseSerializer.class) -public class OneSeriesPointsResponse { - - public final List> points; - -} diff --git a/src/main/java/de/ph87/data/series/point/OneSeriesPointsResponseSerializer.java b/src/main/java/de/ph87/data/series/point/OneSeriesPointsResponseSerializer.java deleted file mode 100644 index e398e5f..0000000 --- a/src/main/java/de/ph87/data/series/point/OneSeriesPointsResponseSerializer.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.ph87.data.series.point; - -import tools.jackson.core.JacksonException; -import tools.jackson.core.JsonGenerator; -import tools.jackson.databind.SerializationContext; -import tools.jackson.databind.ValueSerializer; - -public class OneSeriesPointsResponseSerializer extends ValueSerializer { - - @Override - public void serialize(final OneSeriesPointsResponse value, final JsonGenerator gen, final SerializationContext ctxt) throws JacksonException { - gen.writeStartArray(); - for (final SeriesPoint point : value.points) { - gen.writeStartArray(); - point.toJson(gen); - gen.writeEndArray(); - } - gen.writeEndArray(); - } - -} diff --git a/src/main/java/de/ph87/data/series/point/SeriesPoint.java b/src/main/java/de/ph87/data/series/point/SeriesPoint.java deleted file mode 100644 index 759dd10..0000000 --- a/src/main/java/de/ph87/data/series/point/SeriesPoint.java +++ /dev/null @@ -1,66 +0,0 @@ -package de.ph87.data.series.point; - -import de.ph87.data.plot.axis.graph.GraphDivisionByZero; -import de.ph87.data.plot.axis.graph.GraphOperation; -import lombok.NonNull; -import tools.jackson.core.JsonGenerator; - -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public interface SeriesPoint> { - - ZonedDateTime getDate(); - - double getValue(); - - void toJson(final JsonGenerator jsonGenerator); - - T times(final double factor); - - T combine(@NonNull final SeriesPoint other, @NonNull final GraphOperation operation) throws GraphDivisionByZero; - - @NonNull - static List> combine(@NonNull final List> points1, @NonNull final List> points2, @NonNull final GraphOperation operation) { - if (points1.isEmpty() || points2.isEmpty()) { - return Collections.emptyList(); - } - final List> as = new ArrayList<>(points1); - final List> bs = new ArrayList<>(points2); - SeriesPoint a = as.removeFirst(); - SeriesPoint b = bs.removeFirst(); - final List> result = new ArrayList<>(Math.min(as.size(), bs.size())); - while (true) { - final int diff = a.getDate().compareTo(b.getDate()); - if (diff == 0) { - try { - result.add(a.combine(b, operation)); - } catch (GraphDivisionByZero e) { - // just not add - } - a = null; - b = null; - } else if (diff < 0) { - a = null; - } else { - b = null; - } - if (a == null) { - if (as.isEmpty()) { - break; - } - a = as.removeFirst(); - } - if (b == null) { - if (bs.isEmpty()) { - break; - } - b = bs.removeFirst(); - } - } - return result; - } - -} diff --git a/src/main/java/de/ph87/data/series/point/SeriesPointService.java b/src/main/java/de/ph87/data/series/point/SeriesPointService.java deleted file mode 100644 index bc90953..0000000 --- a/src/main/java/de/ph87/data/series/point/SeriesPointService.java +++ /dev/null @@ -1,100 +0,0 @@ -package de.ph87.data.series.point; - -import de.ph87.data.series.HistoryDto; -import de.ph87.data.series.Series; -import de.ph87.data.series.SeriesDto; -import de.ph87.data.series.SeriesService; -import de.ph87.data.series.data.Interval; -import de.ph87.data.series.data.bool.BoolService; -import de.ph87.data.series.data.delta.DeltaService; -import de.ph87.data.series.data.varying.VaryingService; -import jakarta.annotation.Nullable; -import lombok.Data; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.time.ZonedDateTime; -import java.util.List; - -@Slf4j -@Service -@RequiredArgsConstructor -public class SeriesPointService { - - private final BoolService boolService; - - private final DeltaService deltaService; - - private final VaryingService varyingService; - - private final SeriesService seriesService; - - @NonNull - public OneSeriesPointsResponse oneSeriesPoints(@NonNull final OneSeriesPointsRequest request) { - final Series series1 = seriesService.getById(request.id); - final List> points1 = getSeriesPoints(series1, request, request.factor); - if (request.id2 != null) { - final Series series2 = seriesService.getById(request.id2); - final List> points2 = getSeriesPoints(series2, request, request.factor2); - return new OneSeriesPointsResponse(SeriesPoint.combine(points1, points2, request.operation)); - } - return new OneSeriesPointsResponse(points1); - } - - @NonNull - public AllSeriesPointResponse allSeriesPoint(@NonNull final AllSeriesPointRequest request) { - final List seriesPoints = seriesService.findAll().stream().map(series -> map(series, request)).toList(); - return new AllSeriesPointResponse(request, seriesPoints); - } - - @NonNull - private AllSeriesPointResponse.Entry map(@NonNull final Series series, @NonNull final ISeriesPointRequest request) { - final List> points = getSeriesPoints(series, request, null); - final SeriesDto seriesDto = new SeriesDto(series); - final SeriesPoint point = points.isEmpty() ? null : points.getFirst(); - return new AllSeriesPointResponse.Entry(seriesDto, point); - } - - @NonNull - private List> getSeriesPoints(@NonNull final Series series, @NonNull final ISeriesPointRequest request, @Nullable final Double factor) { - final List> points = switch (series.getType()) { - case BOOL -> boolService.points(series, request); - case DELTA -> deltaService.points(series, request); - case VARYING -> varyingService.points(series, request); - }; - if (factor == null || factor == 1) { - return points; - } - return points.stream().map(p -> p.times(factor)).toList(); - } - - @NonNull - public HistoryDto history(final long id, @NonNull final ZonedDateTime date, @NonNull final Interval interval) { - final Series series = seriesService.getById(id); - final AllSeriesPointResponse.Entry entry = map(series, new Request(date, interval)); - return new HistoryDto(entry); - } - - @Data - private static class Request implements ISeriesPointRequest { - - @NonNull - public final Interval interval; - - @NonNull - public final ZonedDateTime first; - - @NonNull - public final ZonedDateTime after; - - public Request(final @NonNull ZonedDateTime date, final @NonNull Interval interval) { - this.interval = interval; - this.first = interval.align.apply(date); - this.after = this.first.plus(interval.amount, interval.unit); - } - - } - -} diff --git a/src/main/java/de/ph87/data/topic/TopicType.java b/src/main/java/de/ph87/data/topic/TopicType.java index 2f27d13..ef8971a 100644 --- a/src/main/java/de/ph87/data/topic/TopicType.java +++ b/src/main/java/de/ph87/data/topic/TopicType.java @@ -1,8 +1,8 @@ package de.ph87.data.topic; import de.ph87.data.topic.parser.PatrixOpenDtu; -import de.ph87.data.topic.parser.ShellyPlus1PM; import de.ph87.data.topic.parser.PatrixSmartMeter; +import de.ph87.data.topic.parser.ShellyPlus1PM; import de.ph87.data.topic.parser.TasmotaSmartMeter; import lombok.Getter; diff --git a/src/main/java/de/ph87/data/weather/WeatherService.java b/src/main/java/de/ph87/data/weather/WeatherService.java index dd5eb5e..0ba744f 100644 --- a/src/main/java/de/ph87/data/weather/WeatherService.java +++ b/src/main/java/de/ph87/data/weather/WeatherService.java @@ -1,6 +1,5 @@ package de.ph87.data.weather; -import tools.jackson.databind.ObjectMapper; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -9,6 +8,7 @@ import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import tools.jackson.databind.ObjectMapper; import java.io.IOException; import java.net.HttpURLConnection;