mqtt, series, meter, varying, Heizung, OpenDTU, SmartMeter, PatrixJson
This commit is contained in:
commit
606ee34731
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea/modules.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/compiler.xml
|
||||
.idea/libraries/
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
10
application.properties
Normal file
10
application.properties
Normal file
@ -0,0 +1,10 @@
|
||||
logging.level.de.ph87.home=DEBUG
|
||||
#-
|
||||
spring.datasource.url=jdbc:h2:./database;AUTO_SERVER=TRUE
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=password
|
||||
#-
|
||||
#spring.jpa.hibernate.ddl-auto=create
|
||||
#-
|
||||
de.ph87.patrix.mqtt.host=10.0.0.50
|
||||
32
pom.xml
Normal file
32
pom.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>Home</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<parent>
|
||||
<groupId>de.ph87.patrix</groupId>
|
||||
<artifactId>PatrixParent</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>de.ph87.patrix</groupId>
|
||||
<artifactId>PatrixCrud</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.ph87.patrix</groupId>
|
||||
<artifactId>PatrixMqtt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.units</groupId>
|
||||
<artifactId>indriya</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
15
src/main/java/de/ph87/home/Backend.java
Normal file
15
src/main/java/de/ph87/home/Backend.java
Normal file
@ -0,0 +1,15 @@
|
||||
package de.ph87.home;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan(basePackages = {"de.ph87.home", "de.ph87.patrix"})
|
||||
public class Backend {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Backend.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
58
src/main/java/de/ph87/home/meter/Meter.java
Normal file
58
src/main/java/de/ph87/home/meter/Meter.java
Normal file
@ -0,0 +1,58 @@
|
||||
package de.ph87.home.meter;
|
||||
|
||||
import de.ph87.home.series.Series;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static de.ph87.home.unit.UnitHelper.convert;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
public class Meter {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Version
|
||||
@ToString.Exclude
|
||||
private long version;
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
@ManyToOne(optional = false)
|
||||
private Series series;
|
||||
|
||||
@NonNull
|
||||
@ToString.Include
|
||||
public String series() {
|
||||
return series.getName();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false)
|
||||
private ZonedDateTime since;
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false)
|
||||
private String number;
|
||||
|
||||
@Column(nullable = false, name = "`value`")
|
||||
private double value;
|
||||
|
||||
public Meter(@NonNull final Series series, @NonNull final ZonedDateTime since, @NonNull final String number, @NonNull final ComparableQuantity<?> value) {
|
||||
this.series = series;
|
||||
this.since = since;
|
||||
this.number = number;
|
||||
this.value = convert(value, series.getUnit()).getValue().doubleValue();
|
||||
}
|
||||
|
||||
}
|
||||
14
src/main/java/de/ph87/home/meter/MeterRepository.java
Normal file
14
src/main/java/de/ph87/home/meter/MeterRepository.java
Normal file
@ -0,0 +1,14 @@
|
||||
package de.ph87.home.meter;
|
||||
|
||||
import de.ph87.home.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> findFirstBySeriesOrderBySinceDesc(@NonNull final Series series);
|
||||
|
||||
}
|
||||
29
src/main/java/de/ph87/home/meter/MeterService.java
Normal file
29
src/main/java/de/ph87/home/meter/MeterService.java
Normal file
@ -0,0 +1,29 @@
|
||||
package de.ph87.home.meter;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueInbound;
|
||||
import de.ph87.home.series.Series;
|
||||
import de.ph87.home.series.SeriesService;
|
||||
import de.ph87.home.series.Type;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MeterService {
|
||||
|
||||
private final MeterRepository meterRepository;
|
||||
|
||||
private final SeriesService seriesService;
|
||||
|
||||
@NonNull
|
||||
public Meter getOrCreate(@NonNull final MeterValueInbound event) {
|
||||
final Series series = seriesService.getOrCreate(event.getName(), Type.METER, event.value.getUnit());
|
||||
return meterRepository.findFirstBySeriesOrderBySinceDesc(series)
|
||||
.filter(meter -> meter.getNumber().equals(event.getNumber()))
|
||||
.orElseGet(() -> meterRepository.save(new Meter(series, event.getDate(), event.getNumber(), event.getValue())));
|
||||
}
|
||||
|
||||
}
|
||||
19
src/main/java/de/ph87/home/meter/value/MeterPoint.java
Normal file
19
src/main/java/de/ph87/home/meter/value/MeterPoint.java
Normal file
@ -0,0 +1,19 @@
|
||||
package de.ph87.home.meter.value;
|
||||
|
||||
import de.ph87.home.point.PointResult;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Getter
|
||||
public class MeterPoint extends PointResult.Point {
|
||||
|
||||
public final double delta;
|
||||
|
||||
public MeterPoint(@NonNull final ZonedDateTime date, final double delta) {
|
||||
super(date);
|
||||
this.delta = delta;
|
||||
}
|
||||
|
||||
}
|
||||
82
src/main/java/de/ph87/home/meter/value/MeterValue.java
Normal file
82
src/main/java/de/ph87/home/meter/value/MeterValue.java
Normal file
@ -0,0 +1,82 @@
|
||||
package de.ph87.home.meter.value;
|
||||
|
||||
import de.ph87.home.meter.Meter;
|
||||
import de.ph87.home.unit.Aligned;
|
||||
import de.ph87.home.unit.Interval;
|
||||
import de.ph87.home.unit.UnitHelper;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@MappedSuperclass
|
||||
@NoArgsConstructor
|
||||
public abstract class MeterValue {
|
||||
|
||||
@EmbeddedId
|
||||
private Id id;
|
||||
|
||||
@Column(nullable = false, updatable = false)
|
||||
private double min;
|
||||
|
||||
@Column(nullable = false)
|
||||
private double max;
|
||||
|
||||
protected MeterValue(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
this.id = id;
|
||||
this.min = UnitHelper.convert(value, id.meter.getSeries().getUnit()).getValue().doubleValue();
|
||||
this.max = this.min;
|
||||
}
|
||||
|
||||
public void update(@NonNull final ComparableQuantity<?> value) {
|
||||
final double converted = UnitHelper.convert(value, id.meter.getSeries().getUnit()).getValue().doubleValue();
|
||||
if (converted < min) {
|
||||
throw new RuntimeException("Meter cannot run backwards: MeterValue=%s, inbound=%s".formatted(this, value));
|
||||
}
|
||||
min = Math.min(converted, min);
|
||||
max = Math.max(converted, max);
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Embeddable
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor
|
||||
public static class Id {
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
@ManyToOne(optional = false)
|
||||
private Meter meter;
|
||||
|
||||
@NonNull
|
||||
@ToString.Include
|
||||
public String series() {
|
||||
return meter.series();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ToString.Include
|
||||
public String meter() {
|
||||
return meter.getNumber();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false, updatable = false)
|
||||
private ZonedDateTime date;
|
||||
|
||||
public Id(@NonNull final Interval interval, @NonNull final ZonedDateTime date, @NonNull final Meter meter) {
|
||||
this.date = new Aligned(date, interval).date;
|
||||
this.meter = meter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "%s()";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package de.ph87.home.meter.value;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Data
|
||||
public class MeterValueInbound {
|
||||
|
||||
@NonNull
|
||||
public final String name;
|
||||
|
||||
@NonNull
|
||||
public final String number;
|
||||
|
||||
@NonNull
|
||||
public final ZonedDateTime date;
|
||||
|
||||
@NonNull
|
||||
public final ComparableQuantity<?> value;
|
||||
|
||||
public MeterValueInbound(@NonNull final String name, @NonNull final String number, final long date, @NonNull final ComparableQuantity<?> value) {
|
||||
this(name, number, ZonedDateTime.ofInstant(Instant.ofEpochSecond(date), ZoneId.systemDefault()), value);
|
||||
}
|
||||
|
||||
public MeterValueInbound(@NonNull final String name, @NonNull final String number, @NonNull final ZonedDateTime date, @NonNull final ComparableQuantity<?> value) {
|
||||
this.name = name;
|
||||
this.number = number;
|
||||
this.date = date;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,75 @@
|
||||
package de.ph87.home.meter.value;
|
||||
|
||||
import de.ph87.home.meter.Meter;
|
||||
import de.ph87.home.meter.MeterService;
|
||||
import de.ph87.home.meter.value.day.MeterDay;
|
||||
import de.ph87.home.meter.value.day.MeterDayRepository;
|
||||
import de.ph87.home.meter.value.five.MeterFive;
|
||||
import de.ph87.home.meter.value.five.MeterFiveRepository;
|
||||
import de.ph87.home.meter.value.hour.MeterHour;
|
||||
import de.ph87.home.meter.value.hour.MeterHourRepository;
|
||||
import de.ph87.home.meter.value.month.MeterMonth;
|
||||
import de.ph87.home.meter.value.month.MeterMonthRepository;
|
||||
import de.ph87.home.meter.value.week.MeterWeek;
|
||||
import de.ph87.home.meter.value.week.MeterWeekRepository;
|
||||
import de.ph87.home.meter.value.year.MeterYear;
|
||||
import de.ph87.home.meter.value.year.MeterYearRepository;
|
||||
import de.ph87.home.unit.Interval;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MeterValueReceiver {
|
||||
|
||||
private final MeterFiveRepository meterFiveRepository;
|
||||
|
||||
private final MeterHourRepository meterHourRepository;
|
||||
|
||||
private final MeterDayRepository meterDayRepository;
|
||||
|
||||
private final MeterWeekRepository meterWeekRepository;
|
||||
|
||||
private final MeterMonthRepository meterMonthRepository;
|
||||
|
||||
private final MeterYearRepository meterYearRepository;
|
||||
|
||||
private final MeterService meterService;
|
||||
|
||||
@Transactional
|
||||
@EventListener
|
||||
public void onMeterInbound(@NonNull final MeterValueInbound event) {
|
||||
final Meter meter = meterService.getOrCreate(event);
|
||||
updateOrCreate(event, meter, Interval.FIVE, MeterFive::new, meterFiveRepository);
|
||||
updateOrCreate(event, meter, Interval.HOUR, MeterHour::new, meterHourRepository);
|
||||
updateOrCreate(event, meter, Interval.DAY, MeterDay::new, meterDayRepository);
|
||||
updateOrCreate(event, meter, Interval.WEEK, MeterWeek::new, meterWeekRepository);
|
||||
updateOrCreate(event, meter, Interval.MONTH, MeterMonth::new, meterMonthRepository);
|
||||
updateOrCreate(event, meter, Interval.YEAR, MeterYear::new, meterYearRepository);
|
||||
}
|
||||
|
||||
private <T extends MeterValue> void updateOrCreate(
|
||||
@NonNull final MeterValueInbound event,
|
||||
@NonNull final Meter meter,
|
||||
@NonNull final Interval interval,
|
||||
@NonNull final BiFunction<MeterValue.Id, ComparableQuantity<?>, T> create,
|
||||
@NonNull final MeterValueRepository<T> repository
|
||||
) {
|
||||
final MeterYear.Id id = new MeterValue.Id(interval, event.getDate(), meter);
|
||||
repository
|
||||
.findById(id)
|
||||
.ifPresentOrElse(
|
||||
existing -> existing.update(event.getValue()),
|
||||
() -> repository.save(create.apply(id, event.getValue()))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package de.ph87.home.meter.value;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface MeterValueRepository<T extends MeterValue> extends ListCrudRepository<T, MeterValue.Id> {
|
||||
|
||||
@Query("select new de.ph87.home.meter.value.MeterPoint(v.id.date, sum(v.max - v.min)) from #{#entityName} v where v.id.meter.series.id = :id and v.id.date >= :first and v.id.date <= :last group by v.id.date")
|
||||
List<MeterPoint> points(@NonNull long id, @NonNull ZonedDateTime first, @NonNull ZonedDateTime last);
|
||||
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
package de.ph87.home.meter.value;
|
||||
|
||||
import de.ph87.home.meter.value.day.MeterDayRepository;
|
||||
import de.ph87.home.meter.value.five.MeterFiveRepository;
|
||||
import de.ph87.home.meter.value.hour.MeterHourRepository;
|
||||
import de.ph87.home.meter.value.month.MeterMonthRepository;
|
||||
import de.ph87.home.meter.value.week.MeterWeekRepository;
|
||||
import de.ph87.home.meter.value.year.MeterYearRepository;
|
||||
import de.ph87.home.point.PointRequest;
|
||||
import de.ph87.home.series.SeriesDto;
|
||||
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 MeterValueService {
|
||||
|
||||
private final MeterFiveRepository meterFiveRepository;
|
||||
|
||||
private final MeterHourRepository meterHourRepository;
|
||||
|
||||
private final MeterDayRepository meterDayRepository;
|
||||
|
||||
private final MeterWeekRepository meterWeekRepository;
|
||||
|
||||
private final MeterMonthRepository meterMonthRepository;
|
||||
|
||||
private final MeterYearRepository meterYearRepository;
|
||||
|
||||
@NonNull
|
||||
public List<MeterPoint> points(@NonNull final SeriesDto series, @NonNull final PointRequest request) {
|
||||
return switch (request.getInner()) {
|
||||
case FIVE -> meterFiveRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case HOUR -> meterHourRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case DAY -> meterDayRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case WEEK -> meterWeekRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case MONTH -> meterMonthRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case YEAR -> meterYearRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/meter/value/day/MeterDay.java
Normal file
21
src/main/java/de/ph87/home/meter/value/day/MeterDay.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.meter.value.day;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class MeterDay extends MeterValue {
|
||||
|
||||
public MeterDay(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.meter.value.day;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueRepository;
|
||||
|
||||
public interface MeterDayRepository extends MeterValueRepository<MeterDay> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/meter/value/five/MeterFive.java
Normal file
21
src/main/java/de/ph87/home/meter/value/five/MeterFive.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.meter.value.five;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class MeterFive extends MeterValue {
|
||||
|
||||
public MeterFive(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.meter.value.five;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueRepository;
|
||||
|
||||
public interface MeterFiveRepository extends MeterValueRepository<MeterFive> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/meter/value/hour/MeterHour.java
Normal file
21
src/main/java/de/ph87/home/meter/value/hour/MeterHour.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.meter.value.hour;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class MeterHour extends MeterValue {
|
||||
|
||||
public MeterHour(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.meter.value.hour;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueRepository;
|
||||
|
||||
public interface MeterHourRepository extends MeterValueRepository<MeterHour> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/meter/value/month/MeterMonth.java
Normal file
21
src/main/java/de/ph87/home/meter/value/month/MeterMonth.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.meter.value.month;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class MeterMonth extends MeterValue {
|
||||
|
||||
public MeterMonth(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.meter.value.month;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueRepository;
|
||||
|
||||
public interface MeterMonthRepository extends MeterValueRepository<MeterMonth> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/meter/value/week/MeterWeek.java
Normal file
21
src/main/java/de/ph87/home/meter/value/week/MeterWeek.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.meter.value.week;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class MeterWeek extends MeterValue {
|
||||
|
||||
public MeterWeek(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.meter.value.week;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueRepository;
|
||||
|
||||
public interface MeterWeekRepository extends MeterValueRepository<MeterWeek> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/meter/value/year/MeterYear.java
Normal file
21
src/main/java/de/ph87/home/meter/value/year/MeterYear.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.meter.value.year;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class MeterYear extends MeterValue {
|
||||
|
||||
public MeterYear(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.meter.value.year;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueRepository;
|
||||
|
||||
public interface MeterYearRepository extends MeterValueRepository<MeterYear> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/point/PointController.java
Normal file
21
src/main/java/de/ph87/home/point/PointController.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.point;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
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;
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("points")
|
||||
public class PointController {
|
||||
|
||||
private final PointService pointService;
|
||||
|
||||
@PostMapping
|
||||
public PointResult request(@RequestBody final PointRequest request) {
|
||||
return pointService.request(request);
|
||||
}
|
||||
|
||||
}
|
||||
45
src/main/java/de/ph87/home/point/PointRequest.java
Normal file
45
src/main/java/de/ph87/home/point/PointRequest.java
Normal file
@ -0,0 +1,45 @@
|
||||
package de.ph87.home.point;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import de.ph87.home.unit.Aligned;
|
||||
import de.ph87.home.unit.Interval;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Data
|
||||
public class PointRequest {
|
||||
|
||||
@NonNull
|
||||
public final String seriesName;
|
||||
|
||||
public final long offset;
|
||||
|
||||
public final long count;
|
||||
|
||||
@NonNull
|
||||
public final Interval outer;
|
||||
|
||||
@NonNull
|
||||
public final Interval inner;
|
||||
|
||||
@NonNull
|
||||
@JsonIgnore
|
||||
public final Aligned beginIncluding;
|
||||
|
||||
@NonNull
|
||||
@JsonIgnore
|
||||
public final Aligned endIncluding;
|
||||
|
||||
public PointRequest(@NonNull final String seriesName, final long offset, final long count, @NonNull final Interval outer, @NonNull final Interval inner) {
|
||||
this.seriesName = seriesName;
|
||||
this.offset = offset;
|
||||
this.count = count;
|
||||
this.outer = outer;
|
||||
this.inner = inner;
|
||||
this.endIncluding = new Aligned(ZonedDateTime.now(), outer).minus(offset);
|
||||
this.beginIncluding = endIncluding.minus(this.count - 1);
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/de/ph87/home/point/PointResult.java
Normal file
28
src/main/java/de/ph87/home/point/PointResult.java
Normal file
@ -0,0 +1,28 @@
|
||||
package de.ph87.home.point;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValue;
|
||||
import de.ph87.home.series.SeriesDto;
|
||||
import de.ph87.home.varying.VaryingValue;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class PointResult {
|
||||
|
||||
public final SeriesDto series;
|
||||
|
||||
public final List<? extends Point> points;
|
||||
|
||||
@Data
|
||||
public static abstract class Point {
|
||||
|
||||
@NonNull
|
||||
public final ZonedDateTime date;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
35
src/main/java/de/ph87/home/point/PointService.java
Normal file
35
src/main/java/de/ph87/home/point/PointService.java
Normal file
@ -0,0 +1,35 @@
|
||||
package de.ph87.home.point;
|
||||
|
||||
import de.ph87.home.meter.value.MeterValueService;
|
||||
import de.ph87.home.series.SeriesDto;
|
||||
import de.ph87.home.series.SeriesRepository;
|
||||
import de.ph87.home.varying.VaryingValueService;
|
||||
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 SeriesRepository seriesRepository;
|
||||
|
||||
private final MeterValueService meterValueService;
|
||||
|
||||
private final VaryingValueService varyingValueService;
|
||||
|
||||
@NonNull
|
||||
public PointResult request(@NonNull final PointRequest request) {
|
||||
final SeriesDto series = seriesRepository.findDtoByName(request.getSeriesName()).orElseThrow();
|
||||
final List<? extends PointResult.Point> points = switch (series.getType()) {
|
||||
case METER -> meterValueService.points(series, request);
|
||||
case VARYING -> varyingValueService.points(series, request);
|
||||
};
|
||||
return new PointResult(series, points);
|
||||
}
|
||||
|
||||
}
|
||||
62
src/main/java/de/ph87/home/receive/HeizungHandler.java
Normal file
62
src/main/java/de/ph87/home/receive/HeizungHandler.java
Normal file
@ -0,0 +1,62 @@
|
||||
package de.ph87.home.receive;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.ph87.home.varying.VaryingValueInbound;
|
||||
import de.ph87.patrix.mqtt.MqttEvent;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
import tech.units.indriya.quantity.Quantities;
|
||||
import tech.units.indriya.unit.Units;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class HeizungHandler {
|
||||
|
||||
private static final Pattern REGEX = Pattern.compile("^aggregation/(?<property>heizung/.+)/temperatur$");
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@EventListener
|
||||
public void handle(@NonNull final MqttEvent event) throws Exception {
|
||||
final Matcher matcher = REGEX.matcher(event.topic);
|
||||
if (!matcher.find()) {
|
||||
return;
|
||||
}
|
||||
final String property = matcher.group("property");
|
||||
final Inbound inbound = objectMapper.readValue(event.payload, Inbound.class);
|
||||
applicationEventPublisher.publishEvent(new VaryingValueInbound(property, inbound.date, inbound.value));
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
private static class Inbound {
|
||||
|
||||
@NonNull
|
||||
public final ZonedDateTime date;
|
||||
|
||||
public final ComparableQuantity<?> value;
|
||||
|
||||
public Inbound(final long timestamp, final double sum, final int count) {
|
||||
this.date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
|
||||
this.value = Quantities.getQuantity(sum / count, Units.CELSIUS);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
83
src/main/java/de/ph87/home/receive/OpenDTUHandler.java
Normal file
83
src/main/java/de/ph87/home/receive/OpenDTUHandler.java
Normal file
@ -0,0 +1,83 @@
|
||||
package de.ph87.home.receive;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.ph87.home.meter.value.MeterValueInbound;
|
||||
import de.ph87.home.varying.VaryingValueInbound;
|
||||
import de.ph87.patrix.mqtt.MqttEvent;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
import tech.units.indriya.quantity.Quantities;
|
||||
import tech.units.indriya.unit.Units;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static de.ph87.home.unit.UnitHelper.ENERGY_KILOWATT_HOUR;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class OpenDTUHandler {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@EventListener
|
||||
public void handle(@NonNull final MqttEvent event) throws Exception {
|
||||
if (!"openDTU/pv/patrix/json2".equals(event.topic)) {
|
||||
return;
|
||||
}
|
||||
final Inbound inbound = objectMapper.readValue(event.payload, Inbound.class);
|
||||
applicationEventPublisher.publishEvent(new VaryingValueInbound("electricity/producing", inbound.date, inbound.producing));
|
||||
applicationEventPublisher.publishEvent(new MeterValueInbound("electricity/produced", inbound.inverter, inbound.date, inbound.produced));
|
||||
applicationEventPublisher.publishEvent(new VaryingValueInbound("electricity/producing/string0", inbound.date, inbound.producing0));
|
||||
applicationEventPublisher.publishEvent(new MeterValueInbound("electricity/produced/string0", inbound.inverter, inbound.date, inbound.produced0));
|
||||
applicationEventPublisher.publishEvent(new VaryingValueInbound("electricity/producing/string1", inbound.date, inbound.producing1));
|
||||
applicationEventPublisher.publishEvent(new MeterValueInbound("electricity/produced/string1", inbound.inverter, inbound.date, inbound.produced1));
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public static class Inbound {
|
||||
|
||||
@NonNull
|
||||
public final String inverter;
|
||||
|
||||
@NonNull
|
||||
public final ZonedDateTime date;
|
||||
|
||||
public final ComparableQuantity<?> produced;
|
||||
|
||||
public final ComparableQuantity<?> producing;
|
||||
|
||||
public final ComparableQuantity<?> produced0;
|
||||
|
||||
public final ComparableQuantity<?> producing0;
|
||||
|
||||
public final ComparableQuantity<?> produced1;
|
||||
|
||||
public final ComparableQuantity<?> producing1;
|
||||
|
||||
public Inbound(final long timestamp, @NonNull final String inverter, final double totalKWh, final double totalW, final double string0KWh, final double string0W, final double string1KWh, final double string1W) {
|
||||
this.inverter = inverter;
|
||||
this.date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
|
||||
this.produced = Quantities.getQuantity(totalKWh, ENERGY_KILOWATT_HOUR);
|
||||
this.producing = Quantities.getQuantity(totalW, Units.WATT);
|
||||
this.produced0 = Quantities.getQuantity(string0KWh, ENERGY_KILOWATT_HOUR);
|
||||
this.producing0 = Quantities.getQuantity(string0W, Units.WATT);
|
||||
this.produced1 = Quantities.getQuantity(string1KWh, ENERGY_KILOWATT_HOUR);
|
||||
this.producing1 = Quantities.getQuantity(string1W, Units.WATT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
73
src/main/java/de/ph87/home/receive/PatrixJsonHandler.java
Normal file
73
src/main/java/de/ph87/home/receive/PatrixJsonHandler.java
Normal file
@ -0,0 +1,73 @@
|
||||
package de.ph87.home.receive;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.ph87.home.meter.value.MeterValueInbound;
|
||||
import de.ph87.home.unit.PatrixUnit;
|
||||
import de.ph87.home.varying.VaryingValueInbound;
|
||||
import de.ph87.patrix.mqtt.MqttEvent;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.units.indriya.quantity.Quantities;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PatrixJsonHandler {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@EventListener
|
||||
public void handle(@NonNull final MqttEvent event) throws Exception {
|
||||
if (!event.topic.endsWith("/PatrixJson")) {
|
||||
return;
|
||||
}
|
||||
final Inbound inbound = objectMapper.readValue(event.payload, Inbound.class);
|
||||
applicationEventPublisher.publishEvent(inbound);
|
||||
}
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(name = "VARYING", value = Varying.class),
|
||||
@JsonSubTypes.Type(name = "METER", value = Meter.class),
|
||||
})
|
||||
private interface Inbound {
|
||||
|
||||
enum Type {
|
||||
VARYING,
|
||||
METER,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ToString(callSuper = true)
|
||||
public static class Varying extends VaryingValueInbound implements Inbound {
|
||||
|
||||
protected Varying(@NonNull final String name, final long date, final double value, @NonNull final PatrixUnit unit) {
|
||||
super(name, ZonedDateTime.ofInstant(Instant.ofEpochSecond(date), ZoneId.systemDefault()), Quantities.getQuantity(value, unit.unit));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ToString(callSuper = true)
|
||||
public static class Meter extends MeterValueInbound implements Inbound {
|
||||
|
||||
protected Meter(@NonNull final String name, @NonNull final String number, final long date, final double value, @NonNull final PatrixUnit unit) {
|
||||
super(name, number, ZonedDateTime.ofInstant(Instant.ofEpochSecond(date), ZoneId.systemDefault()), Quantities.getQuantity(value, unit.unit));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
86
src/main/java/de/ph87/home/receive/SmartMeterHandler.java
Normal file
86
src/main/java/de/ph87/home/receive/SmartMeterHandler.java
Normal file
@ -0,0 +1,86 @@
|
||||
package de.ph87.home.receive;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import de.ph87.home.meter.value.MeterValueInbound;
|
||||
import de.ph87.home.varying.VaryingValueInbound;
|
||||
import de.ph87.patrix.mqtt.MqttEvent;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
import tech.units.indriya.quantity.Quantities;
|
||||
|
||||
import javax.measure.quantity.Energy;
|
||||
import javax.measure.quantity.Power;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static de.ph87.home.unit.UnitHelper.*;
|
||||
import static tech.units.indriya.unit.Units.WATT;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SmartMeterHandler {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@EventListener
|
||||
public void handle(@NonNull final MqttEvent event) throws Exception {
|
||||
if (!"electricity/grid/json".equals(event.topic)) {
|
||||
return;
|
||||
}
|
||||
final Inbound inbound = objectMapper.readValue(event.payload, Inbound.class);
|
||||
applicationEventPublisher.publishEvent(new MeterValueInbound("electricity/purchased", inbound.number, inbound.date, inbound.purchased));
|
||||
applicationEventPublisher.publishEvent(new MeterValueInbound("electricity/delivered", inbound.number, inbound.date, inbound.delivered));
|
||||
applicationEventPublisher.publishEvent(new VaryingValueInbound("electricity/purchasing", inbound.date, inbound.purchasing));
|
||||
applicationEventPublisher.publishEvent(new VaryingValueInbound("electricity/delivering", inbound.date, inbound.delivering));
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public static class Inbound {
|
||||
|
||||
@NonNull
|
||||
public String number = "1ZPA0020300305"; // TODO implement in smart-meter firmware
|
||||
|
||||
@NonNull
|
||||
public final ZonedDateTime date;
|
||||
|
||||
public final ComparableQuantity<Energy> purchased;
|
||||
|
||||
@NonNull
|
||||
public final ComparableQuantity<Energy> delivered;
|
||||
|
||||
@NonNull
|
||||
public final ComparableQuantity<Power> purchasing;
|
||||
|
||||
@NonNull
|
||||
public final ComparableQuantity<Power> delivering;
|
||||
|
||||
public Inbound(
|
||||
final long timestamp,
|
||||
@NonNull final BigDecimal purchaseWh,
|
||||
@NonNull final BigDecimal deliveryWh,
|
||||
@NonNull final BigDecimal powerW
|
||||
) {
|
||||
this.date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
|
||||
this.purchased = Quantities.getQuantity(purchaseWh, ENERGY_WATT_HOUR);
|
||||
this.delivered = Quantities.getQuantity(deliveryWh, ENERGY_WATT_HOUR);
|
||||
final ComparableQuantity<Power> power = Quantities.getQuantity(powerW, WATT);
|
||||
this.purchasing = zeroIfNegative(power);
|
||||
this.delivering = zeroIfNegative(negate(power));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
49
src/main/java/de/ph87/home/series/Series.java
Normal file
49
src/main/java/de/ph87/home/series/Series.java
Normal file
@ -0,0 +1,49 @@
|
||||
package de.ph87.home.series;
|
||||
|
||||
import de.ph87.home.unit.PatrixUnit;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
public class Series {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
@Version
|
||||
@ToString.Exclude
|
||||
private long version;
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false)
|
||||
private String title;
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false, updatable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
private Type type;
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false, updatable = false)
|
||||
@Enumerated(EnumType.STRING)
|
||||
private PatrixUnit unit;
|
||||
|
||||
public Series(@NonNull final String name, @NonNull final Type type, @NonNull final PatrixUnit unit) {
|
||||
this.name = name;
|
||||
this.title = name;
|
||||
this.type = type;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
}
|
||||
32
src/main/java/de/ph87/home/series/SeriesDto.java
Normal file
32
src/main/java/de/ph87/home/series/SeriesDto.java
Normal file
@ -0,0 +1,32 @@
|
||||
package de.ph87.home.series;
|
||||
|
||||
import de.ph87.home.unit.PatrixUnit;
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
|
||||
@Data
|
||||
public class SeriesDto {
|
||||
|
||||
public final long id;
|
||||
|
||||
@NonNull
|
||||
public final String name;
|
||||
|
||||
@NonNull
|
||||
public final String title;
|
||||
|
||||
@NonNull
|
||||
private final Type type;
|
||||
|
||||
@NonNull
|
||||
public final PatrixUnit unit;
|
||||
|
||||
public SeriesDto(@NonNull final Series series) {
|
||||
this.id = series.getId();
|
||||
this.name = series.getName();
|
||||
this.title = series.getTitle();
|
||||
this.type = series.getType();
|
||||
this.unit = series.getUnit();
|
||||
}
|
||||
|
||||
}
|
||||
16
src/main/java/de/ph87/home/series/SeriesRepository.java
Normal file
16
src/main/java/de/ph87/home/series/SeriesRepository.java
Normal file
@ -0,0 +1,16 @@
|
||||
package de.ph87.home.series;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface SeriesRepository extends ListCrudRepository<Series, Long> {
|
||||
|
||||
Optional<Series> findByName(@NonNull String name);
|
||||
|
||||
@Query("select new de.ph87.home.series.SeriesDto(s) from Series s where s.name = :name")
|
||||
Optional<SeriesDto> findDtoByName(@NonNull String name);
|
||||
|
||||
}
|
||||
29
src/main/java/de/ph87/home/series/SeriesService.java
Normal file
29
src/main/java/de/ph87/home/series/SeriesService.java
Normal file
@ -0,0 +1,29 @@
|
||||
package de.ph87.home.series;
|
||||
|
||||
import de.ph87.home.unit.PatrixUnit;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SeriesService {
|
||||
|
||||
private final SeriesRepository seriesRepository;
|
||||
|
||||
@NonNull
|
||||
@Transactional
|
||||
public Series getOrCreate(@NonNull final String name, final @NonNull Type type, @NonNull final Unit<?> unit) {
|
||||
return seriesRepository.findByName(name).orElseGet(() -> {
|
||||
final Series fresh = new Series(name, type, PatrixUnit.from(unit));
|
||||
log.info("Series CREATED: {}", fresh);
|
||||
return seriesRepository.save(fresh);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
6
src/main/java/de/ph87/home/series/Type.java
Normal file
6
src/main/java/de/ph87/home/series/Type.java
Normal file
@ -0,0 +1,6 @@
|
||||
package de.ph87.home.series;
|
||||
|
||||
public enum Type {
|
||||
VARYING,
|
||||
METER,
|
||||
}
|
||||
32
src/main/java/de/ph87/home/unit/Aligned.java
Normal file
32
src/main/java/de/ph87/home/unit/Aligned.java
Normal file
@ -0,0 +1,32 @@
|
||||
package de.ph87.home.unit;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Data
|
||||
public class Aligned {
|
||||
|
||||
@NonNull
|
||||
public final ZonedDateTime date;
|
||||
|
||||
@NonNull
|
||||
public final Interval interval;
|
||||
|
||||
public Aligned(@NonNull final ZonedDateTime date, @NonNull final Interval interval) {
|
||||
this.date = interval.align.apply(date);
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public Aligned(@NonNull final Aligned aligned, final long plusAmount) {
|
||||
this.date = aligned.interval.plus.apply(aligned.date, plusAmount);
|
||||
this.interval = aligned.interval;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Aligned minus(final long amount) {
|
||||
return new Aligned(this, -amount);
|
||||
}
|
||||
|
||||
}
|
||||
29
src/main/java/de/ph87/home/unit/Interval.java
Normal file
29
src/main/java/de/ph87/home/unit/Interval.java
Normal file
@ -0,0 +1,29 @@
|
||||
package de.ph87.home.unit;
|
||||
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
public enum Interval {
|
||||
FIVE(date -> date.truncatedTo(ChronoUnit.MINUTES).minusMinutes(date.getMinute() % 5), (date, amount) -> date.plusMinutes(5 * amount)),
|
||||
HOUR(date -> date.truncatedTo(ChronoUnit.HOURS), ZonedDateTime::plusHours),
|
||||
DAY(date -> date.truncatedTo(ChronoUnit.DAYS), ZonedDateTime::plusDays),
|
||||
WEEK(date -> date.truncatedTo(ChronoUnit.DAYS).minusDays(date.getDayOfWeek().getValue() - 1), (date, amount) -> date.plusDays(7 * amount)),
|
||||
MONTH(date -> date.truncatedTo(ChronoUnit.DAYS).withDayOfMonth(1), ZonedDateTime::plusMonths),
|
||||
YEAR(date -> date.truncatedTo(ChronoUnit.DAYS).withDayOfYear(1), ZonedDateTime::plusYears),
|
||||
;
|
||||
|
||||
@NonNull
|
||||
public final Function<ZonedDateTime, ZonedDateTime> align;
|
||||
|
||||
public final BiFunction<ZonedDateTime, Long, ZonedDateTime> plus;
|
||||
|
||||
Interval(@NonNull final Function<ZonedDateTime, ZonedDateTime> align, final BiFunction<ZonedDateTime, Long, ZonedDateTime> plus) {
|
||||
this.align = align;
|
||||
this.plus = plus;
|
||||
}
|
||||
|
||||
}
|
||||
45
src/main/java/de/ph87/home/unit/PatrixUnit.java
Normal file
45
src/main/java/de/ph87/home/unit/PatrixUnit.java
Normal file
@ -0,0 +1,45 @@
|
||||
package de.ph87.home.unit;
|
||||
|
||||
import lombok.NonNull;
|
||||
import tech.units.indriya.AbstractUnit;
|
||||
import tech.units.indriya.unit.Units;
|
||||
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.Unit;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static de.ph87.home.unit.UnitHelper.ENERGY_KILOWATT_HOUR;
|
||||
|
||||
public enum PatrixUnit {
|
||||
BOOLEAN(AbstractUnit.ONE),
|
||||
VOLUME_L(Units.LITRE),
|
||||
VOLUME_MM3(Units.LITRE.divide(1000000)),
|
||||
LENGTH_CM(Units.METRE.divide(100)),
|
||||
|
||||
POWER_W(Units.WATT),
|
||||
ENERGY_KWH(ENERGY_KILOWATT_HOUR),
|
||||
|
||||
// TODO
|
||||
IAQ(AbstractUnit.ONE),
|
||||
IAQ_CO2_EQUIVALENT(AbstractUnit.ONE),
|
||||
IAQ_VOC_EQUIVALENT(AbstractUnit.ONE),
|
||||
PRESSURE_HPA(AbstractUnit.ONE),
|
||||
TEMPERATURE_C(Units.CELSIUS),
|
||||
HUMIDITY_RELATIVE_PERCENT(AbstractUnit.ONE),
|
||||
HUMIDITY_ABSOLUTE_GM3(AbstractUnit.ONE),
|
||||
SUN_DC(AbstractUnit.ONE),
|
||||
;
|
||||
|
||||
@NonNull
|
||||
public final Unit<? extends Quantity<?>> unit;
|
||||
|
||||
<T extends Quantity<T>> PatrixUnit(@NonNull final Unit<T> unit) {
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static PatrixUnit from(@NonNull final Unit<?> unit) {
|
||||
return Arrays.stream(values()).filter(u -> u.unit.isCompatible(unit)).findFirst().orElseThrow();
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/de/ph87/home/unit/QuantityConverter.java
Normal file
28
src/main/java/de/ph87/home/unit/QuantityConverter.java
Normal file
@ -0,0 +1,28 @@
|
||||
package de.ph87.home.unit;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
import tech.units.indriya.format.SimpleQuantityFormat;
|
||||
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.format.QuantityFormat;
|
||||
|
||||
@Converter(autoApply = true)
|
||||
public class QuantityConverter implements AttributeConverter<Quantity<?>, String> {
|
||||
|
||||
public static final QuantityFormat FORMAT = SimpleQuantityFormat.getInstance();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String convertToDatabaseColumn(@Nullable Quantity<?> quantity) {
|
||||
return quantity == null ? null : FORMAT.format(quantity);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Quantity<?> convertToEntityAttribute(@Nullable String string) {
|
||||
return string == null ? null : FORMAT.parse(string);
|
||||
}
|
||||
|
||||
}
|
||||
41
src/main/java/de/ph87/home/unit/UnitHelper.java
Normal file
41
src/main/java/de/ph87/home/unit/UnitHelper.java
Normal file
@ -0,0 +1,41 @@
|
||||
package de.ph87.home.unit;
|
||||
|
||||
import lombok.NonNull;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
import tech.units.indriya.quantity.Quantities;
|
||||
|
||||
import javax.measure.MetricPrefix;
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.Unit;
|
||||
import javax.measure.quantity.Energy;
|
||||
|
||||
import static tech.units.indriya.unit.Units.HOUR;
|
||||
import static tech.units.indriya.unit.Units.WATT;
|
||||
|
||||
public class UnitHelper {
|
||||
|
||||
public static final Unit<Energy> ENERGY_WATT_HOUR = WATT.multiply(HOUR).asType(Energy.class);
|
||||
|
||||
public static final Unit<Energy> ENERGY_KILOWATT_HOUR = MetricPrefix.KILO(ENERGY_WATT_HOUR);
|
||||
|
||||
@NonNull
|
||||
public static <T extends Quantity<T>> ComparableQuantity<T> zeroIfNegative(final ComparableQuantity<T> value) {
|
||||
final ComparableQuantity<T> zero = Quantities.getQuantity(0, value.getUnit());
|
||||
return value.isGreaterThanOrEqualTo(zero) ? value : zero;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T extends Quantity<T>> ComparableQuantity<T> negate(final ComparableQuantity<T> value) {
|
||||
return value.multiply(-1);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <Q extends Quantity<Q>> ComparableQuantity<Q> convert(@NonNull final ComparableQuantity<?> value, @NonNull final PatrixUnit unit) {
|
||||
if (!value.getUnit().isCompatible(unit.unit)) {
|
||||
throw new RuntimeException("Incompatible units: value=%s, targetUnit=%s".formatted(value, unit));
|
||||
}
|
||||
//noinspection unchecked
|
||||
return ((ComparableQuantity<Q>) value).to((Unit<Q>) unit.unit);
|
||||
}
|
||||
|
||||
}
|
||||
25
src/main/java/de/ph87/home/varying/VaryingPoint.java
Normal file
25
src/main/java/de/ph87/home/varying/VaryingPoint.java
Normal file
@ -0,0 +1,25 @@
|
||||
package de.ph87.home.varying;
|
||||
|
||||
import de.ph87.home.point.PointResult;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Getter
|
||||
public class VaryingPoint extends PointResult.Point {
|
||||
|
||||
public final double min;
|
||||
|
||||
public final double max;
|
||||
|
||||
public final double avg;
|
||||
|
||||
public VaryingPoint(@NonNull final ZonedDateTime date, final double min, final double max, final double avg) {
|
||||
super(date);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.avg = avg;
|
||||
}
|
||||
|
||||
}
|
||||
80
src/main/java/de/ph87/home/varying/VaryingValue.java
Normal file
80
src/main/java/de/ph87/home/varying/VaryingValue.java
Normal file
@ -0,0 +1,80 @@
|
||||
package de.ph87.home.varying;
|
||||
|
||||
import de.ph87.home.series.Series;
|
||||
import de.ph87.home.unit.Aligned;
|
||||
import de.ph87.home.unit.Interval;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import static de.ph87.home.unit.UnitHelper.convert;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@MappedSuperclass
|
||||
@NoArgsConstructor
|
||||
public abstract class VaryingValue {
|
||||
|
||||
@EmbeddedId
|
||||
private Id id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private double min;
|
||||
|
||||
@Column(nullable = false)
|
||||
private double max;
|
||||
|
||||
@Column(nullable = false)
|
||||
private double avg;
|
||||
|
||||
@Column(nullable = false)
|
||||
private long count;
|
||||
|
||||
protected VaryingValue(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
this.id = id;
|
||||
final double converted = convert(value, id.series.getUnit()).getValue().doubleValue();
|
||||
this.min = converted;
|
||||
this.max = converted;
|
||||
this.avg = converted;
|
||||
}
|
||||
|
||||
public void update(@NonNull final ComparableQuantity<?> value) {
|
||||
final double converted = convert(value, id.series.getUnit()).getValue().doubleValue();
|
||||
min = Math.min(min, converted);
|
||||
max = Math.max(max, converted);
|
||||
avg = (avg * count + converted) / (count + 1);
|
||||
count++;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@Embeddable
|
||||
@EqualsAndHashCode
|
||||
@NoArgsConstructor
|
||||
public static class Id {
|
||||
|
||||
@NonNull
|
||||
@ToString.Exclude
|
||||
@ManyToOne(optional = false)
|
||||
private Series series;
|
||||
|
||||
@NonNull
|
||||
@ToString.Include
|
||||
public String series() {
|
||||
return series.getName();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Column(nullable = false, updatable = false)
|
||||
private ZonedDateTime date;
|
||||
|
||||
public Id(@NonNull final Interval interval, @NonNull final ZonedDateTime date, @NonNull final Series series) {
|
||||
this.date = new Aligned(date, interval).date;
|
||||
this.series = series;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
33
src/main/java/de/ph87/home/varying/VaryingValueInbound.java
Normal file
33
src/main/java/de/ph87/home/varying/VaryingValueInbound.java
Normal file
@ -0,0 +1,33 @@
|
||||
package de.ph87.home.varying;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NonNull;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Data
|
||||
public class VaryingValueInbound {
|
||||
|
||||
@NonNull
|
||||
public final String name;
|
||||
|
||||
@NonNull
|
||||
public final ZonedDateTime date;
|
||||
|
||||
@NonNull
|
||||
public final ComparableQuantity<?> value;
|
||||
|
||||
public VaryingValueInbound(@NonNull final String name, final long date, @NonNull final ComparableQuantity<?> value) {
|
||||
this(name, ZonedDateTime.ofInstant(Instant.ofEpochSecond(date), ZoneId.systemDefault()), value);
|
||||
}
|
||||
|
||||
public VaryingValueInbound(@NonNull final String name, @NonNull final ZonedDateTime date, @NonNull final ComparableQuantity<?> value) {
|
||||
this.name = name;
|
||||
this.date = date;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
76
src/main/java/de/ph87/home/varying/VaryingValueReceiver.java
Normal file
76
src/main/java/de/ph87/home/varying/VaryingValueReceiver.java
Normal file
@ -0,0 +1,76 @@
|
||||
package de.ph87.home.varying;
|
||||
|
||||
import de.ph87.home.series.Series;
|
||||
import de.ph87.home.series.SeriesService;
|
||||
import de.ph87.home.series.Type;
|
||||
import de.ph87.home.unit.Interval;
|
||||
import de.ph87.home.varying.day.VaryingDay;
|
||||
import de.ph87.home.varying.day.VaryingDayRepository;
|
||||
import de.ph87.home.varying.five.VaryingFive;
|
||||
import de.ph87.home.varying.five.VaryingFiveRepository;
|
||||
import de.ph87.home.varying.hour.VaryingHour;
|
||||
import de.ph87.home.varying.hour.VaryingHourRepository;
|
||||
import de.ph87.home.varying.month.VaryingMonth;
|
||||
import de.ph87.home.varying.month.VaryingMonthRepository;
|
||||
import de.ph87.home.varying.week.VaryingWeek;
|
||||
import de.ph87.home.varying.week.VaryingWeekRepository;
|
||||
import de.ph87.home.varying.year.VaryingYear;
|
||||
import de.ph87.home.varying.year.VaryingYearRepository;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class VaryingValueReceiver {
|
||||
|
||||
private final VaryingFiveRepository varyingFiveRepository;
|
||||
|
||||
private final VaryingHourRepository varyingHourRepository;
|
||||
|
||||
private final VaryingDayRepository varyingDayRepository;
|
||||
|
||||
private final VaryingWeekRepository varyingWeekRepository;
|
||||
|
||||
private final VaryingMonthRepository varyingMonthRepository;
|
||||
|
||||
private final VaryingYearRepository varyingYearRepository;
|
||||
|
||||
private final SeriesService seriesService;
|
||||
|
||||
@Transactional
|
||||
@EventListener
|
||||
public void onVaryingInbound(@NonNull final VaryingValueInbound event) {
|
||||
final Series series = seriesService.getOrCreate(event.getName(), Type.VARYING, event.value.getUnit());
|
||||
updateOrCreate(event, series, Interval.FIVE, VaryingFive::new, varyingFiveRepository);
|
||||
updateOrCreate(event, series, Interval.HOUR, VaryingHour::new, varyingHourRepository);
|
||||
updateOrCreate(event, series, Interval.DAY, VaryingDay::new, varyingDayRepository);
|
||||
updateOrCreate(event, series, Interval.WEEK, VaryingWeek::new, varyingWeekRepository);
|
||||
updateOrCreate(event, series, Interval.MONTH, VaryingMonth::new, varyingMonthRepository);
|
||||
updateOrCreate(event, series, Interval.YEAR, VaryingYear::new, varyingYearRepository);
|
||||
}
|
||||
|
||||
private <T extends VaryingValue> void updateOrCreate(
|
||||
@NonNull final VaryingValueInbound event,
|
||||
@NonNull final Series series,
|
||||
@NonNull final Interval interval,
|
||||
@NonNull final BiFunction<VaryingValue.Id, ComparableQuantity<?>, T> create,
|
||||
@NonNull final VaryingValueRepository<T> repository
|
||||
) {
|
||||
final VaryingYear.Id id = new VaryingValue.Id(interval, event.getDate(), series);
|
||||
repository
|
||||
.findById(id)
|
||||
.ifPresentOrElse(
|
||||
existing -> existing.update(event.getValue()),
|
||||
() -> repository.save(create.apply(id, event.getValue()))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package de.ph87.home.varying;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.ListCrudRepository;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface VaryingValueRepository<T extends VaryingValue> extends ListCrudRepository<T, VaryingValue.Id> {
|
||||
|
||||
@Query("select new de.ph87.home.varying.VaryingPoint(v.id.date, v.min, v.max, v.avg) from #{#entityName} v where v.id.series.id = :id and v.id.date >= :begin and v.id.date < :end")
|
||||
List<VaryingPoint> points(@NonNull final long seriesId, @NonNull final ZonedDateTime begin, @NonNull final ZonedDateTime end);
|
||||
|
||||
}
|
||||
45
src/main/java/de/ph87/home/varying/VaryingValueService.java
Normal file
45
src/main/java/de/ph87/home/varying/VaryingValueService.java
Normal file
@ -0,0 +1,45 @@
|
||||
package de.ph87.home.varying;
|
||||
|
||||
import de.ph87.home.point.PointRequest;
|
||||
import de.ph87.home.series.SeriesDto;
|
||||
import de.ph87.home.varying.day.VaryingDayRepository;
|
||||
import de.ph87.home.varying.five.VaryingFiveRepository;
|
||||
import de.ph87.home.varying.hour.VaryingHourRepository;
|
||||
import de.ph87.home.varying.month.VaryingMonthRepository;
|
||||
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 VaryingValueService {
|
||||
|
||||
private final VaryingFiveRepository varyingFiveRepository;
|
||||
|
||||
private final VaryingHourRepository varyingHourRepository;
|
||||
|
||||
private final VaryingDayRepository varyingDayRepository;
|
||||
|
||||
private final de.ph87.home.varying.week.VaryingWeekRepository varyingWeekRepository;
|
||||
|
||||
private final VaryingMonthRepository varyingMonthRepository;
|
||||
|
||||
private final de.ph87.home.varying.year.VaryingYearRepository varyingYearRepository;
|
||||
|
||||
@NonNull
|
||||
public List<VaryingPoint> points(@NonNull final SeriesDto series, @NonNull final PointRequest request) {
|
||||
return switch (request.getInner()) {
|
||||
case FIVE -> varyingFiveRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case HOUR -> varyingHourRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case DAY -> varyingDayRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case WEEK -> varyingWeekRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case MONTH -> varyingMonthRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
case YEAR -> varyingYearRepository.points(series.id, request.beginIncluding.date, request.endIncluding.date);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/varying/day/VaryingDay.java
Normal file
21
src/main/java/de/ph87/home/varying/day/VaryingDay.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.varying.day;
|
||||
|
||||
import de.ph87.home.varying.VaryingValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class VaryingDay extends VaryingValue {
|
||||
|
||||
public VaryingDay(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.varying.day;
|
||||
|
||||
import de.ph87.home.varying.VaryingValueRepository;
|
||||
|
||||
public interface VaryingDayRepository extends VaryingValueRepository<VaryingDay> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/varying/five/VaryingFive.java
Normal file
21
src/main/java/de/ph87/home/varying/five/VaryingFive.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.varying.five;
|
||||
|
||||
import de.ph87.home.varying.VaryingValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class VaryingFive extends VaryingValue {
|
||||
|
||||
public VaryingFive(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.varying.five;
|
||||
|
||||
import de.ph87.home.varying.VaryingValueRepository;
|
||||
|
||||
public interface VaryingFiveRepository extends VaryingValueRepository<VaryingFive> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/varying/hour/VaryingHour.java
Normal file
21
src/main/java/de/ph87/home/varying/hour/VaryingHour.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.varying.hour;
|
||||
|
||||
import de.ph87.home.varying.VaryingValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class VaryingHour extends VaryingValue {
|
||||
|
||||
public VaryingHour(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.varying.hour;
|
||||
|
||||
import de.ph87.home.varying.VaryingValueRepository;
|
||||
|
||||
public interface VaryingHourRepository extends VaryingValueRepository<VaryingHour> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/varying/month/VaryingMonth.java
Normal file
21
src/main/java/de/ph87/home/varying/month/VaryingMonth.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.varying.month;
|
||||
|
||||
import de.ph87.home.varying.VaryingValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class VaryingMonth extends VaryingValue {
|
||||
|
||||
public VaryingMonth(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.varying.month;
|
||||
|
||||
import de.ph87.home.varying.VaryingValueRepository;
|
||||
|
||||
public interface VaryingMonthRepository extends VaryingValueRepository<VaryingMonth> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/varying/week/VaryingWeek.java
Normal file
21
src/main/java/de/ph87/home/varying/week/VaryingWeek.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.varying.week;
|
||||
|
||||
import de.ph87.home.varying.VaryingValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class VaryingWeek extends VaryingValue {
|
||||
|
||||
public VaryingWeek(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.varying.week;
|
||||
|
||||
import de.ph87.home.varying.VaryingValueRepository;
|
||||
|
||||
public interface VaryingWeekRepository extends VaryingValueRepository<VaryingWeek> {
|
||||
|
||||
}
|
||||
21
src/main/java/de/ph87/home/varying/year/VaryingYear.java
Normal file
21
src/main/java/de/ph87/home/varying/year/VaryingYear.java
Normal file
@ -0,0 +1,21 @@
|
||||
package de.ph87.home.varying.year;
|
||||
|
||||
import de.ph87.home.varying.VaryingValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import lombok.ToString;
|
||||
import tech.units.indriya.ComparableQuantity;
|
||||
|
||||
@Entity
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
public class VaryingYear extends VaryingValue {
|
||||
|
||||
public VaryingYear(@NonNull final Id id, @NonNull final ComparableQuantity<?> value) {
|
||||
super(id, value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package de.ph87.home.varying.year;
|
||||
|
||||
import de.ph87.home.varying.VaryingValueRepository;
|
||||
|
||||
public interface VaryingYearRepository extends VaryingValueRepository<VaryingYear> {
|
||||
|
||||
}
|
||||
10
src/main/resources/application.properties
Normal file
10
src/main/resources/application.properties
Normal file
@ -0,0 +1,10 @@
|
||||
logging.level.root=WARN
|
||||
logging.level.de.ph87=INFO
|
||||
#-
|
||||
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.open-in-view=false
|
||||
#-
|
||||
spring.jackson.serialization.indent_output=true
|
||||
#-
|
||||
spring.main.banner-mode=off
|
||||
Loading…
Reference in New Issue
Block a user