using spring-boot:repackage + some minor fixes + clean up

This commit is contained in:
Patrick Haßel 2021-10-03 21:39:47 +02:00
parent fc7058c0e0
commit 25d78dc32a
10 changed files with 94 additions and 141 deletions

6
deploy.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
cd "$(dirname "$0")" || exit 1
mvn clean package spring-boot:repackage && \
scp target/Homeautomation.jar media@10.0.0.50:/home/media/Homeautomation/Homeautomation.jar

98
pom.xml
View File

@ -7,18 +7,16 @@
<groupId>de.ph87</groupId> <groupId>de.ph87</groupId>
<artifactId>Homeautomation</artifactId> <artifactId>Homeautomation</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties> <properties>
<maven.compiler.source>11</maven.compiler.source> <maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>15</maven.compiler.target>
</properties> </properties>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.6.RELEASE</version> <version>2.3.6.RELEASE</version>
<relativePath/>
</parent> </parent>
<dependencies> <dependencies>
@ -50,11 +48,13 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.calimero</groupId> <groupId>com.github.calimero</groupId>
<artifactId>calimero-core</artifactId> <artifactId>calimero-core</artifactId>
<version>2.5-M1</version> <version>2.5-rc1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.luckycatlabs</groupId> <groupId>com.luckycatlabs</groupId>
@ -71,95 +71,27 @@
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<executions> <executions>
<execution> <execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration> <configuration>
<classifier>spring-boot</classifier> <mainClass>de.ph87.homeautomation.BackendApplication</mainClass>
<mainClass>
de.ph87.de.ph87.homeautomation.BackendApplication
</mainClass>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- <plugin>-->
<!-- <groupId>com.github.eirslett</groupId>-->
<!-- <artifactId>frontend-maven-plugin</artifactId>-->
<!-- <version>1.10.3</version>-->
<!-- <configuration>-->
<!-- <workingDirectory>src/main/angular</workingDirectory>-->
<!-- </configuration>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>install-node-and-npm</id>-->
<!-- <goals>-->
<!-- <goal>install-node-and-npm</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <nodeVersion>v14.15.5</nodeVersion>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- <execution>-->
<!-- <id>npm install</id>-->
<!-- <goals>-->
<!-- <goal>npm</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <arguments>install</arguments>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- <execution>-->
<!-- <id>npm build</id>-->
<!-- <phase>generate-resources</phase>-->
<!-- <goals>-->
<!-- <goal>npm</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <arguments>run build</arguments>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<!-- <plugin>-->
<!-- <artifactId>maven-resources-plugin</artifactId>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>copy-resources</id>-->
<!-- <phase>process-resources</phase>-->
<!-- <goals>-->
<!-- <goal>copy-resources</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <outputDirectory>target/classes/resources/</outputDirectory>-->
<!-- <resources>-->
<!-- <resource>-->
<!-- <directory>src/main/angular/dist/angular/</directory>-->
<!-- </resource>-->
<!-- </resources>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
<!-- <configuration>-->
<!-- <source>11</source>-->
<!-- <target>11</target>-->
<!-- </configuration>-->
<!-- </plugin>-->
</plugins> </plugins>
</build> </build>

View File

@ -1,6 +1,7 @@
package de.ph87.homeautomation; package de.ph87.homeautomation;
import com.luckycatlabs.sunrisesunset.Zenith; import com.luckycatlabs.sunrisesunset.Zenith;
import de.ph87.homeautomation.knx.group.KnxGroupRepository;
import de.ph87.homeautomation.knx.group.KnxGroupWriteService; import de.ph87.homeautomation.knx.group.KnxGroupWriteService;
import de.ph87.homeautomation.schedule.PropertyEntry; import de.ph87.homeautomation.schedule.PropertyEntry;
import de.ph87.homeautomation.schedule.Schedule; import de.ph87.homeautomation.schedule.Schedule;
@ -36,13 +37,15 @@ public class DemoDataService {
private final ScheduleRepository scheduleRepository; private final ScheduleRepository scheduleRepository;
private final KnxGroupRepository knxGroupRepository;
@PostConstruct @PostConstruct
public void postConstruct() { public void postConstruct() {
knxGroupWriteService.create("Wohnzimmer Rollladen Position Anfahren", WOHNZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false); createKnxGroupIfNotExists("Wohnzimmer Rollladen Position Anfahren", WOHNZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false);
knxGroupWriteService.create("Schlafzimmer Rollladen Position Anfahren", SCHLAFZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false); createKnxGroupIfNotExists("Schlafzimmer Rollladen Position Anfahren", SCHLAFZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false);
knxGroupWriteService.create("Flur Rollladen Position Anfahren", FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false); createKnxGroupIfNotExists("Flur Rollladen Position Anfahren", FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false);
knxGroupWriteService.create("Badewanne Schalten", BADEWANNE_SCHALTEN, "1.001", false); createKnxGroupIfNotExists("Badewanne Schalten", BADEWANNE_SCHALTEN, "1.001", false);
knxGroupWriteService.create("Badewanne Status", BADEWANNE_STATUS, "1.001", true); createKnxGroupIfNotExists("Badewanne Status", BADEWANNE_STATUS, "1.001", true);
final Schedule wohnzimmer = new Schedule(); final Schedule wohnzimmer = new Schedule();
wohnzimmer.setName("Rollläden Wohnzimmer"); wohnzimmer.setName("Rollläden Wohnzimmer");
@ -62,14 +65,20 @@ public class DemoDataService {
createSunset(flur, Zenith.NAUTICAL, new PropertyEntry(FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "100")); createSunset(flur, Zenith.NAUTICAL, new PropertyEntry(FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "100"));
scheduleRepository.save(flur); scheduleRepository.save(flur);
// final Schedule badewanne = new Schedule(); final Schedule badewanne = new Schedule();
// badewanne.setName("Badewanne"); badewanne.setName("Badewanne");
// int seconds = 2; int seconds = 2;
// createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "true")); createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "true"));
// createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "false")); createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "false"));
// createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "true")); createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "true"));
// createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "false")); createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "false"));
// scheduleRepository.save(badewanne); scheduleRepository.save(badewanne);
}
private void createKnxGroupIfNotExists(final String name, final GroupAddress address, final String dpt, final boolean readable) {
if (!knxGroupRepository.existsByAddressRaw(address.getRawAddress())) {
knxGroupWriteService.create(name, address, dpt, readable);
}
} }
private ScheduleEntry createRelative(final Schedule schedule, final int inSeconds, final Map.Entry<String, String>... entries) { private ScheduleEntry createRelative(final Schedule schedule, final int inSeconds, final Map.Entry<String, String>... entries) {

View File

@ -129,14 +129,14 @@ public class KnxThreadService extends AbstractThreadService implements NetworkLi
@Override @Override
public void groupReadResponse(final ProcessEvent processEvent) { public void groupReadResponse(final ProcessEvent processEvent) {
synchronized (databaseAccessLock) { synchronized (databaseAccessLock) {
knxGroupWriteService.updateOrCreate(processEvent.getDestination().getRawAddress(), processEvent.getASDU()); knxGroupWriteService.updateIfExists(processEvent.getDestination().getRawAddress(), processEvent.getASDU());
} }
} }
@Override @Override
public void groupWrite(final ProcessEvent processEvent) { public void groupWrite(final ProcessEvent processEvent) {
synchronized (databaseAccessLock) { synchronized (databaseAccessLock) {
knxGroupWriteService.updateOrCreate(processEvent.getDestination().getRawAddress(), processEvent.getASDU()); knxGroupWriteService.updateIfExists(processEvent.getDestination().getRawAddress(), processEvent.getASDU());
} }
} }

View File

@ -47,7 +47,7 @@ public class KnxGroupLinkService {
knxGroup.getSend().setErrorCount(0); knxGroup.getSend().setErrorCount(0);
knxGroup.getSend().setErrorMessage(null); knxGroup.getSend().setErrorMessage(null);
knxGroup.getSend().setNextTimestamp(null); knxGroup.getSend().setNextTimestamp(null);
log.debug("Successfully sent KnxGroup: {}", knxGroup); log.info("Successfully sent KnxGroup: {}", knxGroup);
return true; return true;
} catch (KNXFormatException e) { } catch (KNXFormatException e) {
log.error(e.toString()); log.error(e.toString());

View File

@ -20,4 +20,6 @@ public interface KnxGroupRepository extends CrudRepository<KnxGroup, Long> {
Optional<KnxGroup> findFirstByRead_NextTimestampNotNullOrderByRead_NextTimestampAsc(); Optional<KnxGroup> findFirstByRead_NextTimestampNotNullOrderByRead_NextTimestampAsc();
boolean existsByAddressRaw(int rawAddress);
} }

View File

@ -25,32 +25,27 @@ public class KnxGroupWriteService {
private final KnxGroupRepository knxGroupRepository; private final KnxGroupRepository knxGroupRepository;
public void updateOrCreate(final int rawAddress, final byte[] data) { public void updateIfExists(final int rawAddress, final byte[] data) {
final KnxGroup knxGroup = getOrCreate(rawAddress); final Optional<KnxGroup> knxGroupOptional = knxGroupRepository.findByAddressRaw(rawAddress);
knxGroup.setValue(data); if (knxGroupOptional.isEmpty()) {
knxGroup.setValueTimestamp(ZonedDateTime.now()); log.debug("No KnxGroup with address={}", new GroupAddress(rawAddress));
knxGroup.setBooleanValue(null);
knxGroup.setNumberValue(null);
try {
final DPTXlator translator = findTranslator(knxGroup);
translator.setData(data);
if (translator instanceof DPTXlatorBoolean) {
knxGroup.setBooleanValue(((DPTXlatorBoolean) translator).getValueBoolean());
}
// TODO implement all DPTXlator...
} catch (NoTranslatorException e) {
log.error(e.getMessage());
} }
log.debug("KnxGroup updated: {}", knxGroup); knxGroupOptional.ifPresent(knxGroup -> {
} knxGroup.setValue(data);
knxGroup.setValueTimestamp(ZonedDateTime.now());
private KnxGroup getOrCreate(final int rawAddress) { knxGroup.setBooleanValue(null);
return knxGroupRepository.findByAddressRaw(rawAddress).orElseGet(() -> { knxGroup.setNumberValue(null);
final KnxGroup trans = new KnxGroup(); try {
trans.setAddress(rawAddress); final DPTXlator translator = findTranslator(knxGroup);
final KnxGroup saved = knxGroupRepository.save(trans); translator.setData(data);
log.info("KnxGroup created: {}", saved); if (translator instanceof DPTXlatorBoolean) {
return saved; knxGroup.setBooleanValue(((DPTXlatorBoolean) translator).getValueBoolean());
}
// TODO implement all DPTXlator...
} catch (NoTranslatorException e) {
log.error(e.getMessage());
}
log.debug("KnxGroup updated: {}", knxGroup);
}); });
} }
@ -58,10 +53,6 @@ public class KnxGroupWriteService {
knxGroupRepository.findAllByRead_AbleTrue().forEach(knxGroup -> knxGroup.getRead().setNextTimestamp(ZonedDateTime.now())); knxGroupRepository.findAllByRead_AbleTrue().forEach(knxGroup -> knxGroup.getRead().setNextTimestamp(ZonedDateTime.now()));
} }
public void create(final String name, final int main, final int middle, final int sub, final String dpt, final boolean readable) {
create(name, new GroupAddress(main, middle, sub), dpt, readable);
}
public void create(final String name, final GroupAddress address, final String dpt, final boolean readable) { public void create(final String name, final GroupAddress address, final String dpt, final boolean readable) {
final KnxGroup trans = new KnxGroup(); final KnxGroup trans = new KnxGroup();
trans.setAddress(address); trans.setAddress(address);

View File

@ -27,8 +27,8 @@ public class ScheduleThreadService extends AbstractThreadService {
@Override @Override
protected long doStep() throws InterruptedException { protected long doStep() throws InterruptedException {
scheduleWriteService.executeAllDue(); scheduleWriteService.executeAllLastDue();
return scheduleWriteService.getOverallNextTimestamp().map(nextTimestamp -> Duration.between(ZonedDateTime.now(), nextTimestamp).toMillis()).orElse(0L); return scheduleWriteService.getNextTimestamp().map(nextTimestamp -> Duration.between(ZonedDateTime.now(), nextTimestamp).toMillis()).orElse(0L);
} }
@Override @Override

View File

@ -39,22 +39,22 @@ public class ScheduleWriteService {
public void calculateAllNext() { public void calculateAllNext() {
final ZonedDateTime now = ZonedDateTime.now(); final ZonedDateTime now = ZonedDateTime.now();
scheduleRepository.findAll().forEach(schedule -> schedule.getEntries().forEach(entry -> calculateNext(schedule, entry, now))); scheduleRepository.findAll().forEach(schedule -> calculateSchedule(schedule, now));
} }
public void executeAllDue() { public void executeAllLastDue() {
final ZonedDateTime now = ZonedDateTime.now(); final ZonedDateTime now = ZonedDateTime.now();
scheduleRepository.findAll().forEach(schedule -> executeIfDue(schedule, now)); scheduleRepository.findAll().forEach(schedule -> executeLastDue(schedule, now));
} }
private void executeIfDue(final Schedule schedule, final ZonedDateTime now) { private void executeLastDue(final Schedule schedule, final ZonedDateTime now) {
schedule.getEntries().stream() schedule.getEntries().stream()
.filter(entry -> entry.getNextDateTime() != null && !entry.getNextDateTime().isAfter(now)) .filter(entry -> entry.getNextDateTime() != null && !entry.getNextDateTime().isAfter(now))
.max(Comparator.comparing(ScheduleEntry::getNextDateTime)) .max(Comparator.comparing(ScheduleEntry::getNextDateTime))
.ifPresent(entry -> { .ifPresent(entry -> {
log.info("Executing ScheduleEntry {}", entry); log.info("Executing ScheduleEntry {}", entry);
calculateNext(schedule, entry, now);
entry.getProperties().forEach(this::applyPropertyMapEntry); entry.getProperties().forEach(this::applyPropertyMapEntry);
calculateSchedule(schedule, now);
}); });
} }
@ -66,24 +66,32 @@ public class ScheduleWriteService {
} }
} }
private void calculateNext(final Schedule schedule, final ScheduleEntry entry, final ZonedDateTime now) { private void calculateSchedule(final Schedule schedule, final ZonedDateTime now) {
schedule.getEntries().forEach(scheduleEntry -> calculateEntry(schedule, scheduleEntry, now));
schedule.getEntries().stream()
.filter(entry -> entry.getNextDateTime() != null && entry.getNextDateTime().isAfter(now))
.min(Comparator.comparing(ScheduleEntry::getNextDateTime))
.ifPresent(scheduleEntry -> log.info("Next schedule for \"{}\": {}", schedule.getName(), scheduleEntry.getNextDateTime()));
}
private void calculateEntry(final Schedule schedule, final ScheduleEntry entry, final ZonedDateTime now) {
log.debug("calculateNext \"{}\", {}:", schedule.getName(), entry); log.debug("calculateNext \"{}\", {}:", schedule.getName(), entry);
if (!entry.isEnabled() || !isAnyWeekdayEnabled(entry)) { if (!entry.isEnabled() || !isAnyWeekdayEnabled(entry)) {
entry.setNextDateTime(null); entry.setNextDateTime(null);
return; return;
} }
ZonedDateTime midnight = now.withHour(0).withMinute(0).withSecond(0).withNano(0); ZonedDateTime midnight = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
ZonedDateTime next = nextForDay(entry, midnight); ZonedDateTime next = calculateEntryForDay(entry, midnight);
while (next != null && (!next.isAfter(now) || !isWeekdayValid(entry, next))) { while (next != null && (!next.isAfter(now) || !isWeekdayValid(entry, next))) {
log.debug(" -- skipping: {}", next); log.debug(" -- skipping: {}", next);
midnight = midnight.plusDays(1); midnight = midnight.plusDays(1);
next = nextForDay(entry, midnight); next = calculateEntryForDay(entry, midnight);
} }
log.debug(" => {}", next); log.debug(" => {}", next);
entry.setNextDateTime(next); entry.setNextDateTime(next);
} }
private ZonedDateTime nextForDay(final ScheduleEntry entry, final ZonedDateTime midnight) { private ZonedDateTime calculateEntryForDay(final ScheduleEntry entry, final ZonedDateTime midnight) {
switch (entry.getType()) { switch (entry.getType()) {
case TIME: case TIME:
return midnight.withHour(entry.getHour()).withMinute(entry.getMinute()).withSecond(entry.getSecond()); return midnight.withHour(entry.getHour()).withMinute(entry.getMinute()).withSecond(entry.getSecond());
@ -142,7 +150,7 @@ public class ScheduleWriteService {
return false; return false;
} }
public Optional<ZonedDateTime> getOverallNextTimestamp() { public Optional<ZonedDateTime> getNextTimestamp() {
return scheduleEntryRepository.findFirstNextDateTimeByNextDateTimeNotNullOrderByNextDateTimeAsc().map(ScheduleEntry::getNextDateTime); return scheduleEntryRepository.findFirstNextDateTimeByNextDateTimeNotNullOrderByNextDateTimeAsc().map(ScheduleEntry::getNextDateTime);
} }

View File

@ -21,6 +21,8 @@ public abstract class AbstractThreadService {
private final Object lock = new Object(); private final Object lock = new Object();
private boolean started = false;
private boolean stopped = false; private boolean stopped = false;
protected abstract String getThreadName(); protected abstract String getThreadName();
@ -35,6 +37,9 @@ public abstract class AbstractThreadService {
@EventListener(ApplicationStartedEvent.class) @EventListener(ApplicationStartedEvent.class)
public void afterStartup() { public void afterStartup() {
synchronized (lock) {
started = true;
}
thread.start(); thread.start();
} }
@ -46,7 +51,7 @@ public abstract class AbstractThreadService {
synchronized (lock) { synchronized (lock) {
lock.notifyAll(); lock.notifyAll();
try { try {
while (!stopped) { while (started && !stopped) {
lock.wait(); lock.wait();
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {