Meter
This commit is contained in:
parent
e88ff035cf
commit
e454ed610e
@ -16,4 +16,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="bodyContent">
|
||||||
<router-outlet/>
|
<router-outlet/>
|
||||||
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
@sidebarColor: #62b0ca;
|
@sidebarColor: #62b0ca;
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
margin-left: -2em;
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@ -49,3 +48,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bodyContent {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|||||||
@ -8,13 +8,15 @@ import {NTU, UTN} from '../../COMMON';
|
|||||||
import {Graph} from '../axis/graph/Graph';
|
import {Graph} from '../axis/graph/Graph';
|
||||||
import {Axis} from '../axis/Axis';
|
import {Axis} from '../axis/Axis';
|
||||||
import {Subscription} from 'rxjs';
|
import {Subscription} from 'rxjs';
|
||||||
import {Delta, DeltaService} from '../../series/delta/delta-service';
|
import {DeltaService} from '../../series/delta/delta-service';
|
||||||
import {Bool, BoolService} from '../../series/bool/bool-service';
|
import {BoolService} from '../../series/bool/bool-service';
|
||||||
import {VaryingService} from '../../series/varying/varying-service';
|
import {VaryingService} from '../../series/varying/varying-service';
|
||||||
import {Interval} from '../../series/Interval';
|
import {Interval} from '../../series/Interval';
|
||||||
import {SeriesService} from '../../series/series.service';
|
import {SeriesService} from '../../series/series.service';
|
||||||
import {GraphType} from '../axis/graph/GraphType';
|
import {GraphType} from '../axis/graph/GraphType';
|
||||||
import {Varying} from '../../series/varying/Varying';
|
import {Varying} from '../../series/varying/Varying';
|
||||||
|
import {Delta} from '../../series/delta/Delta';
|
||||||
|
import {Bool} from '../../series/bool/Bool';
|
||||||
|
|
||||||
type Dataset = ChartDataset<any, any>[][number];
|
type Dataset = ChartDataset<any, any>[][number];
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ export function toDelta(points: number[][], factor: number): Point[] {
|
|||||||
for (const p of points) {
|
for (const p of points) {
|
||||||
result.push({
|
result.push({
|
||||||
x: p[0] * 1000,
|
x: p[0] * 1000,
|
||||||
y: (p[2] - p[1]) * factor,
|
y: (p[1]) * factor,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
26
src/main/angular/src/app/series/bool/Bool.ts
Normal file
26
src/main/angular/src/app/series/bool/Bool.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import {Series} from "../Series";
|
||||||
|
import {validateBoolean, validateDate} from "../../COMMON";
|
||||||
|
|
||||||
|
export class Bool {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly series: Series,
|
||||||
|
readonly date: Date,
|
||||||
|
readonly end: Date,
|
||||||
|
readonly state: boolean,
|
||||||
|
readonly terminated: boolean,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json: any): Bool {
|
||||||
|
return new Bool(
|
||||||
|
Series.fromJson(json.series),
|
||||||
|
validateDate(json.date),
|
||||||
|
validateDate(json.end),
|
||||||
|
validateBoolean(json.state),
|
||||||
|
validateBoolean(json.terminated),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,30 +1,6 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {ApiService, CrudService, validateBoolean, validateDate} from '../../COMMON';
|
import {ApiService, CrudService} from '../../COMMON';
|
||||||
import {Series} from '../Series';
|
import {Bool} from './Bool';
|
||||||
|
|
||||||
export class Bool {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly series: Series,
|
|
||||||
readonly date: Date,
|
|
||||||
readonly end: Date,
|
|
||||||
readonly state: boolean,
|
|
||||||
readonly terminated: boolean,
|
|
||||||
) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(json: any): Bool {
|
|
||||||
return new Bool(
|
|
||||||
Series.fromJson(json.series),
|
|
||||||
validateDate(json.date),
|
|
||||||
validateDate(json.end),
|
|
||||||
validateBoolean(json.state),
|
|
||||||
validateBoolean(json.terminated),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
|||||||
24
src/main/angular/src/app/series/delta/Delta.ts
Normal file
24
src/main/angular/src/app/series/delta/Delta.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {validateDate, validateNumber} from "../../COMMON";
|
||||||
|
import {Meter} from './meter/Meter';
|
||||||
|
|
||||||
|
export class Delta {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly meter: Meter,
|
||||||
|
readonly date: Date,
|
||||||
|
readonly first: number,
|
||||||
|
readonly last: number,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json: any): Delta {
|
||||||
|
return new Delta(
|
||||||
|
Meter.fromJson(json.meter),
|
||||||
|
validateDate(json.date),
|
||||||
|
validateNumber(json.first),
|
||||||
|
validateNumber(json.last),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,28 +1,6 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {ApiService, CrudService, validateDate, validateNumber} from '../../COMMON';
|
import {ApiService, CrudService} from '../../COMMON';
|
||||||
import {Series} from '../Series';
|
import {Delta} from './Delta';
|
||||||
|
|
||||||
export class Delta {
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly series: Series,
|
|
||||||
readonly date: Date,
|
|
||||||
readonly first: number,
|
|
||||||
readonly last: number,
|
|
||||||
) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromJson(json: any): Delta {
|
|
||||||
return new Delta(
|
|
||||||
Series.fromJson(json.series),
|
|
||||||
validateDate(json.date),
|
|
||||||
validateNumber(json.first),
|
|
||||||
validateNumber(json.last),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
|||||||
24
src/main/angular/src/app/series/delta/meter/Meter.ts
Normal file
24
src/main/angular/src/app/series/delta/meter/Meter.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {Series} from "../../Series";
|
||||||
|
import {validateDate, validateNumber, validateString} from "../../../COMMON";
|
||||||
|
|
||||||
|
export class Meter {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly id: number,
|
||||||
|
readonly series: Series,
|
||||||
|
readonly number: string,
|
||||||
|
readonly first: Date,
|
||||||
|
) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJson(json: any): Meter {
|
||||||
|
return new Meter(
|
||||||
|
validateNumber(json.id),
|
||||||
|
Series.fromJson(json.series),
|
||||||
|
validateString(json.number),
|
||||||
|
validateDate(json.first),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -17,6 +17,8 @@ export class Topic {
|
|||||||
readonly timestampType: TimestampType,
|
readonly timestampType: TimestampType,
|
||||||
readonly timestampQuery: string,
|
readonly timestampQuery: string,
|
||||||
readonly timestampLast: Date | null,
|
readonly timestampLast: Date | null,
|
||||||
|
readonly meterNumberQuery: string,
|
||||||
|
readonly meterNumberLast: string,
|
||||||
readonly queries: TopicQuery[],
|
readonly queries: TopicQuery[],
|
||||||
readonly payload: string,
|
readonly payload: string,
|
||||||
readonly error: string,
|
readonly error: string,
|
||||||
@ -35,6 +37,8 @@ export class Topic {
|
|||||||
validateString(json.timestampType) as TimestampType,
|
validateString(json.timestampType) as TimestampType,
|
||||||
validateString(json.timestampQuery),
|
validateString(json.timestampQuery),
|
||||||
mapNotNull(json.timestampLast, validateDate),
|
mapNotNull(json.timestampLast, validateDate),
|
||||||
|
validateString(json.meterNumberQuery),
|
||||||
|
validateString(json.meterNumberLast),
|
||||||
validateList(json.queries, TopicQuery.fromJson),
|
validateList(json.queries, TopicQuery.fromJson),
|
||||||
validateString(json.payload),
|
validateString(json.payload),
|
||||||
validateString(json.error),
|
validateString(json.error),
|
||||||
|
|||||||
@ -1,3 +1,8 @@
|
|||||||
|
<div class="options">
|
||||||
|
<label><input type="checkbox" [(ngModel)]="config.topicList.unused">Ungenutzte</label>
|
||||||
|
<label><input type="checkbox" [(ngModel)]="config.topicList.used">Genutzte</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<table class="TopicList">
|
<table class="TopicList">
|
||||||
@for (topic of sorted(); track topic.id) {
|
@for (topic of sorted(); track topic.id) {
|
||||||
<tr class="head">
|
<tr class="head">
|
||||||
@ -10,6 +15,14 @@
|
|||||||
<td class="timestampType" [class.empty]="topic.timestampType === null">{{ topic.timestampType }}</td>
|
<td class="timestampType" [class.empty]="topic.timestampType === null">{{ topic.timestampType }}</td>
|
||||||
<td class="timestampLast" [class.empty]="topic.timestampLast === null" colspan="6">{{ topic.timestampLast | date:'long':'':'de-DE' }}</td>
|
<td class="timestampLast" [class.empty]="topic.timestampLast === null" colspan="6">{{ topic.timestampLast | date:'long':'':'de-DE' }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (topic.queries[0]?.series?.type === SeriesType.DELTA) {
|
||||||
|
<tr class="meter">
|
||||||
|
<td class="meterNumberQuery" [class.empty]="!topic.meterNumberQuery">{{ topic.meterNumberQuery }}</td>
|
||||||
|
<td class="meterNumberLast" [class.empty]="topic.meterNumberLast === null"></td>
|
||||||
|
<td class="meterNumberLast" [class.empty]="topic.meterNumberLast === null" colspan="5">{{ topic.meterNumberLast }}</td>
|
||||||
|
<td class="meterNumberLast" [class.empty]="topic.timestampLast === null">{{ topic.timestampLast | date:'long':'':'de-DE' }}</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
@for (query of topic.queries; track $index) {
|
@for (query of topic.queries; track $index) {
|
||||||
<tr class="query">
|
<tr class="query">
|
||||||
<td class="valueQuery" [class.empty]="query.valueQuery === null">{{ query.valueQuery }}</td>
|
<td class="valueQuery" [class.empty]="query.valueQuery === null">{{ query.valueQuery }}</td>
|
||||||
|
|||||||
@ -22,6 +22,10 @@ table.TopicList {
|
|||||||
background-color: darkseagreen;
|
background-color: darkseagreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tr.meter {
|
||||||
|
background-color: #ffe7bd;
|
||||||
|
}
|
||||||
|
|
||||||
tr.spacer {
|
tr.spacer {
|
||||||
th, td {
|
th, td {
|
||||||
border: none;
|
border: none;
|
||||||
@ -53,7 +57,11 @@ table.TopicList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.timestampLast {
|
.timestampLast {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meterNumberLast {
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.valueQuery {
|
.valueQuery {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {SeriesService} from '../../series/series.service';
|
|||||||
import {Config} from '../../config/Config';
|
import {Config} from '../../config/Config';
|
||||||
import {ageString} from '../../COMMON';
|
import {ageString} from '../../COMMON';
|
||||||
import {ConfigService} from '../../config/config.service';
|
import {ConfigService} from '../../config/config.service';
|
||||||
|
import {SeriesType} from '../../series/SeriesType';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-topic-list',
|
selector: 'app-topic-list',
|
||||||
@ -25,6 +26,8 @@ export class TopicListComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
protected readonly ageString = ageString;
|
protected readonly ageString = ageString;
|
||||||
|
|
||||||
|
protected readonly SeriesType = SeriesType;
|
||||||
|
|
||||||
protected now: Date = new Date();
|
protected now: Date = new Date();
|
||||||
|
|
||||||
protected topicList: Topic[] = [];
|
protected topicList: Topic[] = [];
|
||||||
@ -55,10 +58,6 @@ export class TopicListComponent implements OnInit, OnDestroy {
|
|||||||
this.subs.forEach(sub => sub.unsubscribe());
|
this.subs.forEach(sub => sub.unsubscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
sorted() {
|
|
||||||
return this.topicList.filter(this.filter).sort(this.compare);
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly update = (topic: Topic) => {
|
private readonly update = (topic: Topic) => {
|
||||||
const index = this.topicList.findIndex(t => t.id === topic.id);
|
const index = this.topicList.findIndex(t => t.id === topic.id);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
@ -68,6 +67,10 @@ export class TopicListComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
sorted() {
|
||||||
|
return this.topicList.filter(this.filter).sort(this.compare);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly filter = (topic: Topic) => {
|
private readonly filter = (topic: Topic) => {
|
||||||
return ((!topic.used && this.config.topicList.unused) || (topic.used && this.config.topicList.used));
|
return ((!topic.used && this.config.topicList.unused) || (topic.used && this.config.topicList.used));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ html, body {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
margin-left: 2em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
@ -23,7 +22,7 @@ input, select, textarea {
|
|||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
input, select {
|
input:not([type=checkbox]), select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
|||||||
@ -62,8 +62,9 @@ public class DemoService {
|
|||||||
|
|
||||||
final Series electricityEnergyProduce = series("electricity/energy/produce", "kWh", SeriesType.DELTA, 5);
|
final Series electricityEnergyProduce = series("electricity/energy/produce", "kWh", SeriesType.DELTA, 5);
|
||||||
final Series electricityPowerProduce = series("electricity/power/produce", "W", SeriesType.VARYING, 5);
|
final Series electricityPowerProduce = series("electricity/power/produce", "W", SeriesType.VARYING, 5);
|
||||||
topic(
|
topicMeterNumber(
|
||||||
"openDTU/pv/patrix/json2",
|
"openDTU/pv/patrix/json2",
|
||||||
|
"$.inverter",
|
||||||
new TopicQuery(electricityEnergyProduce, "$.totalKWh"),
|
new TopicQuery(electricityEnergyProduce, "$.totalKWh"),
|
||||||
new TopicQuery(electricityPowerProduce, "$.totalW")
|
new TopicQuery(electricityPowerProduce, "$.totalW")
|
||||||
);
|
);
|
||||||
@ -72,8 +73,9 @@ public class DemoService {
|
|||||||
final Series electricityPowerPurchase = series("electricity/power/purchase", "W", SeriesType.VARYING, 5);
|
final Series electricityPowerPurchase = series("electricity/power/purchase", "W", SeriesType.VARYING, 5);
|
||||||
final Series electricityEnergyDelivery = series("electricity/energy/delivery", "kWh", SeriesType.DELTA, 5);
|
final Series electricityEnergyDelivery = series("electricity/energy/delivery", "kWh", SeriesType.DELTA, 5);
|
||||||
final Series electricityPowerDelivery = series("electricity/power/delivery", "W", SeriesType.VARYING, 5);
|
final Series electricityPowerDelivery = series("electricity/power/delivery", "W", SeriesType.VARYING, 5);
|
||||||
topic(
|
topicMeterNumber(
|
||||||
"electricity/grid/json",
|
"electricity/grid/json",
|
||||||
|
"\"1ZPA0020300305\"",
|
||||||
new TopicQuery(electricityEnergyPurchase, "$.purchaseWh", 0.001),
|
new TopicQuery(electricityEnergyPurchase, "$.purchaseWh", 0.001),
|
||||||
new TopicQuery(electricityPowerPurchase, "$.powerW", TopicQueryFunction.ONLY_POSITIVE),
|
new TopicQuery(electricityPowerPurchase, "$.powerW", TopicQueryFunction.ONLY_POSITIVE),
|
||||||
new TopicQuery(electricityEnergyDelivery, "$.deliveryWh", 0.001),
|
new TopicQuery(electricityEnergyDelivery, "$.deliveryWh", 0.001),
|
||||||
@ -220,4 +222,12 @@ public class DemoService {
|
|||||||
topic.getQueries().addAll(List.of(queries));
|
topic.getQueries().addAll(List.of(queries));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void topicMeterNumber(@NonNull final String name, @NonNull final String meterNumberQuery, @NonNull final TopicQuery... queries) {
|
||||||
|
final Topic topic = topicRepository.findByName(name).orElseGet(() -> topicRepository.save(new Topic(name)));
|
||||||
|
topic.setMeterNumberQuery(meterNumberQuery);
|
||||||
|
topic.setTimestampQuery("$.timestamp");
|
||||||
|
topic.getQueries().clear();
|
||||||
|
topic.getQueries().addAll(List.of(queries));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package de.ph87.data.series.data.delta;
|
package de.ph87.data.series.data.delta;
|
||||||
|
|
||||||
import de.ph87.data.series.data.DataId;
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
@ -19,7 +18,7 @@ public abstract class Delta {
|
|||||||
|
|
||||||
@Id
|
@Id
|
||||||
@NonNull
|
@NonNull
|
||||||
private DataId id;
|
private DeltaId id;
|
||||||
|
|
||||||
@Version
|
@Version
|
||||||
private long version;
|
private long version;
|
||||||
@ -31,7 +30,7 @@ public abstract class Delta {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private double last;
|
private double last;
|
||||||
|
|
||||||
protected Delta(@NonNull final DataId id, final double value) {
|
protected Delta(@NonNull final DeltaId id, final double value) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.first = value;
|
this.first = value;
|
||||||
this.last = value;
|
this.last = value;
|
||||||
@ -47,7 +46,7 @@ public abstract class Delta {
|
|||||||
@Entity(name = "DeltaFive")
|
@Entity(name = "DeltaFive")
|
||||||
public static class Five extends Delta {
|
public static class Five extends Delta {
|
||||||
|
|
||||||
public Five(@NonNull final DataId id, @NonNull final double value) {
|
public Five(@NonNull final DeltaId id, @NonNull final double value) {
|
||||||
super(id, value);
|
super(id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ public abstract class Delta {
|
|||||||
@Entity(name = "DeltaHour")
|
@Entity(name = "DeltaHour")
|
||||||
public static class Hour extends Delta {
|
public static class Hour extends Delta {
|
||||||
|
|
||||||
public Hour(@NonNull final DataId id, @NonNull final double value) {
|
public Hour(@NonNull final DeltaId id, @NonNull final double value) {
|
||||||
super(id, value);
|
super(id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +70,7 @@ public abstract class Delta {
|
|||||||
@Entity(name = "DeltaDay")
|
@Entity(name = "DeltaDay")
|
||||||
public static class Day extends Delta {
|
public static class Day extends Delta {
|
||||||
|
|
||||||
public Day(@NonNull final DataId id, @NonNull final double value) {
|
public Day(@NonNull final DeltaId id, @NonNull final double value) {
|
||||||
super(id, value);
|
super(id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +82,7 @@ public abstract class Delta {
|
|||||||
@Entity(name = "DeltaWeek")
|
@Entity(name = "DeltaWeek")
|
||||||
public static class Week extends Delta {
|
public static class Week extends Delta {
|
||||||
|
|
||||||
public Week(@NonNull final DataId id, @NonNull final double value) {
|
public Week(@NonNull final DeltaId id, @NonNull final double value) {
|
||||||
super(id, value);
|
super(id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ public abstract class Delta {
|
|||||||
@Entity(name = "DeltaMonth")
|
@Entity(name = "DeltaMonth")
|
||||||
public static class Month extends Delta {
|
public static class Month extends Delta {
|
||||||
|
|
||||||
public Month(@NonNull final DataId id, @NonNull final double value) {
|
public Month(@NonNull final DeltaId id, @NonNull final double value) {
|
||||||
super(id, value);
|
super(id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +106,7 @@ public abstract class Delta {
|
|||||||
@Entity(name = "DeltaYear")
|
@Entity(name = "DeltaYear")
|
||||||
public static class Year extends Delta {
|
public static class Year extends Delta {
|
||||||
|
|
||||||
public Year(@NonNull final DataId id, @NonNull final double value) {
|
public Year(@NonNull final DeltaId id, @NonNull final double value) {
|
||||||
super(id, value);
|
super(id, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package de.ph87.data.series.data.delta;
|
package de.ph87.data.series.data.delta;
|
||||||
|
|
||||||
import de.ph87.data.series.SeriesDto;
|
|
||||||
import de.ph87.data.series.data.Interval;
|
import de.ph87.data.series.data.Interval;
|
||||||
|
import de.ph87.data.series.data.delta.meter.MeterDto;
|
||||||
import de.ph87.data.websocket.IWebsocketMessage;
|
import de.ph87.data.websocket.IWebsocketMessage;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -14,21 +14,20 @@ import java.time.ZonedDateTime;
|
|||||||
public abstract class DeltaDto implements IWebsocketMessage {
|
public abstract class DeltaDto implements IWebsocketMessage {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private SeriesDto series;
|
private MeterDto meter;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private ZonedDateTime date;
|
private ZonedDateTime date;
|
||||||
|
|
||||||
public final double first;
|
public final double first;
|
||||||
|
|
||||||
@NonNull
|
|
||||||
public final double last;
|
public final double last;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public final Interval interval;
|
public final Interval interval;
|
||||||
|
|
||||||
protected DeltaDto(@NonNull final Delta delta, @NonNull final Interval interval) {
|
protected DeltaDto(@NonNull final Delta delta, @NonNull final Interval interval) {
|
||||||
this.series = new SeriesDto(delta.getId().getSeries(), false);
|
this.meter = new MeterDto(delta.getId().getMeter());
|
||||||
this.date = delta.getId().getDate();
|
this.date = delta.getId().getDate();
|
||||||
this.first = delta.getFirst();
|
this.first = delta.getFirst();
|
||||||
this.last = delta.getLast();
|
this.last = delta.getLast();
|
||||||
@ -38,7 +37,7 @@ public abstract class DeltaDto implements IWebsocketMessage {
|
|||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String getWebsocketTopic() {
|
public String getWebsocketTopic() {
|
||||||
return "Delta/%d/%s".formatted(series.id, interval);
|
return "Delta/%d/%s".formatted(meter.series.id, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|||||||
36
src/main/java/de/ph87/data/series/data/delta/DeltaId.java
Normal file
36
src/main/java/de/ph87/data/series/data/delta/DeltaId.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package de.ph87.data.series.data.delta;
|
||||||
|
|
||||||
|
import de.ph87.data.series.data.Interval;
|
||||||
|
import de.ph87.data.series.data.delta.meter.Meter;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Embeddable;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@Embeddable
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class DeltaId {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private Meter meter;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Column(nullable = false)
|
||||||
|
private ZonedDateTime date;
|
||||||
|
|
||||||
|
public DeltaId(@NonNull final Meter meter, @NonNull final ZonedDateTime date, @NonNull final Interval interval) {
|
||||||
|
this.meter = meter;
|
||||||
|
this.date = interval.align.apply(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -10,23 +10,20 @@ import java.time.ZonedDateTime;
|
|||||||
@SuppressWarnings("unused") // used by repository query
|
@SuppressWarnings("unused") // used by repository query
|
||||||
public class DeltaPoint implements SeriesPoint {
|
public class DeltaPoint implements SeriesPoint {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public final ZonedDateTime date;
|
public final ZonedDateTime date;
|
||||||
|
|
||||||
public final double first;
|
public final double delta;
|
||||||
|
|
||||||
public final double last;
|
public DeltaPoint(@NonNull final ZonedDateTime date, final double delta) {
|
||||||
|
this.date = date;
|
||||||
public DeltaPoint(@NonNull final Delta delta) {
|
this.delta = delta;
|
||||||
this.date = delta.getId().getDate();
|
|
||||||
this.first = delta.getFirst();
|
|
||||||
this.last = delta.getLast();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toJson(final JsonGenerator jsonGenerator) throws IOException {
|
public void toJson(final JsonGenerator jsonGenerator) throws IOException {
|
||||||
jsonGenerator.writeNumber(date.toEpochSecond());
|
jsonGenerator.writeNumber(date.toEpochSecond());
|
||||||
jsonGenerator.writeNumber(first);
|
jsonGenerator.writeNumber(delta);
|
||||||
jsonGenerator.writeNumber(last);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package de.ph87.data.series.data.delta;
|
package de.ph87.data.series.data.delta;
|
||||||
|
|
||||||
import de.ph87.data.series.Series;
|
import de.ph87.data.series.Series;
|
||||||
import de.ph87.data.series.data.DataId;
|
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.repository.CrudRepository;
|
||||||
@ -11,10 +10,10 @@ import java.time.ZonedDateTime;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@NoRepositoryBean
|
@NoRepositoryBean
|
||||||
public interface DeltaRepo<T extends Delta> extends CrudRepository<T, DataId> {
|
public interface DeltaRepo<T extends Delta> extends CrudRepository<T, DeltaId> {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Query("select new de.ph87.data.series.data.delta.DeltaPoint(e) from #{#entityName} e where e.id.series = :series and e.id.date >= :first and e.id.date < :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 >= :first and e.id.date < :after group by e.id.date")
|
||||||
List<DeltaPoint> points(@NonNull Series series, @NonNull ZonedDateTime first, @NonNull ZonedDateTime after);
|
List<DeltaPoint> points(@NonNull Series series, @NonNull ZonedDateTime first, @NonNull ZonedDateTime after);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,9 @@ package de.ph87.data.series.data.delta;
|
|||||||
|
|
||||||
import de.ph87.data.series.ISeriesPointRequest;
|
import de.ph87.data.series.ISeriesPointRequest;
|
||||||
import de.ph87.data.series.Series;
|
import de.ph87.data.series.Series;
|
||||||
import de.ph87.data.series.data.DataId;
|
|
||||||
import de.ph87.data.series.data.Interval;
|
import de.ph87.data.series.data.Interval;
|
||||||
|
import de.ph87.data.series.data.delta.meter.Meter;
|
||||||
|
import de.ph87.data.series.data.delta.meter.MeterService;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -34,18 +35,21 @@ public class DeltaService {
|
|||||||
|
|
||||||
private final ApplicationEventPublisher applicationEventPublisher;
|
private final ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
|
private final MeterService meterService;
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void write(@NonNull final Series series, @NonNull final ZonedDateTime date, final double value) {
|
public void write(@NonNull final Series series, @NonNull final String meterNumber, @NonNull final ZonedDateTime date, final double value) {
|
||||||
write(series, five, Interval.FIVE, date, value, Delta.Five::new, DeltaDto.Five::new);
|
final Meter meter = meterService.getLastValidBySeriesAndNumberOrCreate(series, meterNumber, date);
|
||||||
write(series, hour, Interval.HOUR, date, value, Delta.Hour::new, DeltaDto.Hour::new);
|
write(meter, five, Interval.FIVE, date, value, Delta.Five::new, DeltaDto.Five::new);
|
||||||
write(series, day, Interval.DAY, date, value, Delta.Day::new, DeltaDto.Day::new);
|
write(meter, hour, Interval.HOUR, date, value, Delta.Hour::new, DeltaDto.Hour::new);
|
||||||
write(series, week, Interval.WEEK, date, value, Delta.Week::new, DeltaDto.Week::new);
|
write(meter, day, Interval.DAY, date, value, Delta.Day::new, DeltaDto.Day::new);
|
||||||
write(series, month, Interval.MONTH, date, value, Delta.Month::new, DeltaDto.Month::new);
|
write(meter, week, Interval.WEEK, date, value, Delta.Week::new, DeltaDto.Week::new);
|
||||||
write(series, year, Interval.YEAR, date, value, Delta.Year::new, DeltaDto.Year::new);
|
write(meter, month, Interval.MONTH, date, value, Delta.Month::new, DeltaDto.Month::new);
|
||||||
|
write(meter, year, Interval.YEAR, date, value, Delta.Year::new, DeltaDto.Year::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <DELTA extends Delta, DTO extends DeltaDto> void write(@NonNull final Series series, @NonNull final DeltaRepo<DELTA> repo, @NonNull final Interval interval, @NonNull final ZonedDateTime date, final double value, @NonNull final BiFunction<DataId, Double, DELTA> create, @NonNull final BiFunction<DELTA, Interval, DTO> toDto) {
|
private <DELTA extends Delta, DTO extends DeltaDto> void write(@NonNull final Meter meter, @NonNull final DeltaRepo<DELTA> repo, @NonNull final Interval interval, @NonNull final ZonedDateTime date, final double value, @NonNull final BiFunction<DeltaId, Double, DELTA> create, @NonNull final BiFunction<DELTA, Interval, DTO> toDto) {
|
||||||
final DataId id = new DataId(series, date, interval);
|
final DeltaId id = new DeltaId(meter, date, interval);
|
||||||
final DELTA delta = repo.findById(id).stream().peek(existing -> existing.update(value)).findFirst().orElseGet(() -> repo.save(create.apply(id, value)));
|
final DELTA delta = repo.findById(id).stream().peek(existing -> existing.update(value)).findFirst().orElseGet(() -> repo.save(create.apply(id, value)));
|
||||||
log.debug("Delta written: {}", delta);
|
log.debug("Delta written: {}", delta);
|
||||||
applicationEventPublisher.publishEvent(toDto.apply(delta, interval));
|
applicationEventPublisher.publishEvent(toDto.apply(delta, interval));
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
package de.ph87.data.series.data.delta.meter;
|
||||||
|
|
||||||
|
import de.ph87.data.series.Series;
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Version;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Meter {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private long version;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
private Series series;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String number;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Column(nullable = false)
|
||||||
|
private ZonedDateTime first;
|
||||||
|
|
||||||
|
public Meter(@NonNull final Series series, @NonNull final String number, @NonNull final ZonedDateTime date) {
|
||||||
|
this.series = series;
|
||||||
|
this.number = number;
|
||||||
|
this.first = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package de.ph87.data.series.data.delta.meter;
|
||||||
|
|
||||||
|
import de.ph87.data.series.SeriesDto;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class MeterDto {
|
||||||
|
|
||||||
|
private final long id;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final SeriesDto series;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final String number;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final ZonedDateTime first;
|
||||||
|
|
||||||
|
public MeterDto(@NonNull final Meter meter) {
|
||||||
|
this.id = meter.getId();
|
||||||
|
this.series = new SeriesDto(meter.getSeries(), false);
|
||||||
|
this.number = meter.getNumber();
|
||||||
|
this.first = meter.getFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package de.ph87.data.series.data.delta.meter;
|
||||||
|
|
||||||
|
import de.ph87.data.series.Series;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import org.springframework.data.repository.ListCrudRepository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface MeterRepository extends ListCrudRepository<Meter, Long> {
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
Optional<Meter> findFirstBySeriesOrderByFirstDesc(@NonNull Series series);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package de.ph87.data.series.data.delta.meter;
|
||||||
|
|
||||||
|
import de.ph87.data.series.Series;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MeterService {
|
||||||
|
|
||||||
|
private final MeterRepository meterRepository;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Transactional
|
||||||
|
public Meter getLastValidBySeriesAndNumberOrCreate(@NonNull final Series series, @NonNull final String number, @NonNull final ZonedDateTime date) {
|
||||||
|
return meterRepository
|
||||||
|
.findFirstBySeriesOrderByFirstDesc(series)
|
||||||
|
.filter(meter -> meter.getNumber().equals(number))
|
||||||
|
.orElseGet(() -> meterRepository.save(new Meter(series, number, date)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -72,6 +72,16 @@ public class Topic extends AbstractEntityLog {
|
|||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
private String timestampQuery = "";
|
private String timestampQuery = "";
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@NonNull
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String meterNumberQuery = "";
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@NonNull
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String meterNumberLast = "";
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
@ElementCollection(fetch = FetchType.EAGER)
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
|
|||||||
@ -36,6 +36,12 @@ public class TopicDto implements IWebsocketMessage {
|
|||||||
@Nullable
|
@Nullable
|
||||||
public final ZonedDateTime timestampLast;
|
public final ZonedDateTime timestampLast;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public final String meterNumberQuery;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public final String meterNumberLast;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public final List<TopicQueryDto> queries;
|
public final List<TopicQueryDto> queries;
|
||||||
|
|
||||||
@ -55,6 +61,8 @@ public class TopicDto implements IWebsocketMessage {
|
|||||||
this.timestampType = topic.getTimestampType();
|
this.timestampType = topic.getTimestampType();
|
||||||
this.timestampQuery = topic.getTimestampQuery();
|
this.timestampQuery = topic.getTimestampQuery();
|
||||||
this.timestampLast = topic.getTimestampLast();
|
this.timestampLast = topic.getTimestampLast();
|
||||||
|
this.meterNumberQuery = topic.getMeterNumberQuery();
|
||||||
|
this.meterNumberLast = topic.getMeterNumberLast();
|
||||||
this.queries = topic.getQueries().stream().map(TopicQueryDto::new).toList();
|
this.queries = topic.getQueries().stream().map(TopicQueryDto::new).toList();
|
||||||
this.error = topic.getError();
|
this.error = topic.getError();
|
||||||
this.payload = topic.getPayload();
|
this.payload = topic.getPayload();
|
||||||
|
|||||||
@ -103,6 +103,12 @@ public class TopicReceiver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (series.getType() == SeriesType.DELTA) {
|
||||||
|
if (topic.getMeterNumberQuery().isEmpty()) {
|
||||||
|
log.debug("TopicQuery meterNumberQuery not set: topic={}", topic);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final Object valueRaw = json.read(query.getValueQuery());
|
final Object valueRaw = json.read(query.getValueQuery());
|
||||||
queryValue(valueRaw).ifPresentOrElse(
|
queryValue(valueRaw).ifPresentOrElse(
|
||||||
@ -110,14 +116,17 @@ public class TopicReceiver {
|
|||||||
final double value = query.getFunction().apply(v) * query.getFactor();
|
final double value = query.getFunction().apply(v) * query.getFactor();
|
||||||
series.update(date, value);
|
series.update(date, value);
|
||||||
applicationEventPublisher.publishEvent(new SeriesDto(series, false));
|
applicationEventPublisher.publishEvent(new SeriesDto(series, false));
|
||||||
|
|
||||||
switch (series.getType()) {
|
switch (series.getType()) {
|
||||||
case BOOL -> {
|
case BOOL -> {
|
||||||
final ZonedDateTime begin = "timestamp".equals(query.getBeginQuery()) ? date : queryTimestamp(json, query.getBeginQuery(), topic.getTimestampType());
|
final ZonedDateTime begin = queryTimestamp(json, query.getBeginQuery(), topic.getTimestampType());
|
||||||
final boolean terminated = !"true".equals(query.getTerminatedQuery()) && json.read(query.getTerminatedQuery(), Boolean.class);
|
final boolean terminated = queryBoolean(json, query.getTerminatedQuery());
|
||||||
boolService.write(series, begin, date, value > 0, terminated);
|
boolService.write(series, begin, date, value > 0, terminated);
|
||||||
}
|
}
|
||||||
case DELTA -> deltaService.write(series, date, value);
|
case DELTA -> {
|
||||||
|
final String meterNumber = queryMeterNumber(topic, json);
|
||||||
|
topic.setMeterNumberLast(meterNumber);
|
||||||
|
deltaService.write(series, meterNumber, date, value);
|
||||||
|
}
|
||||||
case VARYING -> varyingService.write(series, date, value);
|
case VARYING -> varyingService.write(series, date, value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -128,6 +137,24 @@ public class TopicReceiver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static String queryMeterNumber(@NonNull final Topic topic, @NonNull final DocumentContext json) {
|
||||||
|
if (topic.getMeterNumberQuery().startsWith("\"") && topic.getMeterNumberQuery().endsWith("\"")) {
|
||||||
|
return topic.getMeterNumberQuery().substring(1, topic.getMeterNumberQuery().length() - 1);
|
||||||
|
}
|
||||||
|
return json.read(topic.getMeterNumberQuery(), String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean queryBoolean(@NonNull final DocumentContext json, @NonNull final String terminatedQuery) {
|
||||||
|
if ("true".equals(terminatedQuery)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ("false".equals(terminatedQuery)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return json.read(terminatedQuery, Boolean.class);
|
||||||
|
}
|
||||||
|
|
||||||
private static Optional<Double> queryValue(final Object valueRaw) {
|
private static Optional<Double> queryValue(final Object valueRaw) {
|
||||||
if (valueRaw instanceof final Double n) {
|
if (valueRaw instanceof final Double n) {
|
||||||
return Optional.of(n);
|
return Optional.of(n);
|
||||||
@ -148,7 +175,7 @@ public class TopicReceiver {
|
|||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static ZonedDateTime queryTimestamp(@NonNull final DocumentContext json, @NonNull final String query, @NonNull final TimestampType type) {
|
private static ZonedDateTime queryTimestamp(@NonNull final DocumentContext json, @NonNull final String query, @NonNull final TimestampType type) {
|
||||||
if ("now".equals(query)) {
|
if ("now".equals(query) || "timestamp".equals(query)) {
|
||||||
return ZonedDateTime.now();
|
return ZonedDateTime.now();
|
||||||
}
|
}
|
||||||
return switch (type) {
|
return switch (type) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user