KnxLinkService working now
This commit is contained in:
commit
28cf4eed2e
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/target/
|
||||
/.idea/
|
||||
/.jpb/
|
||||
/application.properties
|
||||
160
pom.xml
Normal file
160
pom.xml
Normal file
@ -0,0 +1,160 @@
|
||||
<?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>
|
||||
|
||||
<groupId>de.ph87</groupId>
|
||||
<artifactId>Homeautomation</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.3.6.RELEASE</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.calimero</groupId>
|
||||
<artifactId>calimero-core</artifactId>
|
||||
<version>2.5-M1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<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.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<classifier>spring-boot</classifier>
|
||||
<mainClass>
|
||||
de.ph87.de.ph87.homeautomation.BackendApplication
|
||||
</mainClass>
|
||||
</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>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
54
src/main/java/de/ph87/homeautomation/BackendApplication.java
Normal file
54
src/main/java/de/ph87/homeautomation/BackendApplication.java
Normal file
@ -0,0 +1,54 @@
|
||||
package de.ph87.homeautomation;
|
||||
|
||||
import de.ph87.homeautomation.knx.KnxLinkService;
|
||||
import de.ph87.homeautomation.knx.group.KnxGroup;
|
||||
import de.ph87.homeautomation.knx.group.KnxGroupRepository;
|
||||
import de.ph87.homeautomation.knx.group.KnxGroupWriteService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@SpringBootApplication
|
||||
@RequiredArgsConstructor
|
||||
public class BackendApplication {
|
||||
|
||||
private final KnxGroupRepository knxGroupRepository;
|
||||
|
||||
private final KnxLinkService knxLinkService;
|
||||
|
||||
private final KnxGroupWriteService knxGroupWriteService;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BackendApplication.class);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
knxGroupCreate(0, 0, 1, "1.001");
|
||||
knxGroupCreate(0, 3, 6, "1.001");
|
||||
|
||||
requestAll();
|
||||
}
|
||||
|
||||
private void knxGroupCreate(final int main, final int middle, final int sub, final String dpt) {
|
||||
final KnxGroup trans = new KnxGroup();
|
||||
trans.setAddress(main, middle, sub);
|
||||
trans.setDpt(dpt);
|
||||
knxGroupRepository.save(trans);
|
||||
}
|
||||
|
||||
public void requestAll() {
|
||||
knxGroupWriteService.markAllForRead();
|
||||
knxLinkService.notifyActionPending();
|
||||
}
|
||||
|
||||
@EventListener(ApplicationStartedEvent.class)
|
||||
public void applicationStarted() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
185
src/main/java/de/ph87/homeautomation/knx/KnxLinkService.java
Normal file
185
src/main/java/de/ph87/homeautomation/knx/KnxLinkService.java
Normal file
@ -0,0 +1,185 @@
|
||||
package de.ph87.homeautomation.knx;
|
||||
|
||||
import de.ph87.homeautomation.knx.group.KnxGroupLinkService;
|
||||
import de.ph87.homeautomation.knx.group.KnxGroupWriteService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.event.ApplicationStartedEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tuwien.auto.calimero.CloseEvent;
|
||||
import tuwien.auto.calimero.DetachEvent;
|
||||
import tuwien.auto.calimero.FrameEvent;
|
||||
import tuwien.auto.calimero.KNXException;
|
||||
import tuwien.auto.calimero.link.KNXNetworkLinkIP;
|
||||
import tuwien.auto.calimero.link.NetworkLinkListener;
|
||||
import tuwien.auto.calimero.link.medium.TPSettings;
|
||||
import tuwien.auto.calimero.process.ProcessCommunicatorImpl;
|
||||
import tuwien.auto.calimero.process.ProcessEvent;
|
||||
import tuwien.auto.calimero.process.ProcessListener;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class KnxLinkService implements NetworkLinkListener, ProcessListener {
|
||||
|
||||
public static final int ERROR_DELAY_MS = 3000;
|
||||
|
||||
private final KnxGroupWriteService knxGroupWriteService;
|
||||
|
||||
private final KnxGroupLinkService knxGroupLinkService;
|
||||
|
||||
private InetAddress remoteAddress = null;
|
||||
|
||||
private final Thread thread = new Thread(this::run);
|
||||
|
||||
private boolean stop = false;
|
||||
|
||||
private KNXNetworkLinkIP link = null;
|
||||
|
||||
private ProcessCommunicatorImpl processCommunicator = null;
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
@EventListener(ApplicationStartedEvent.class)
|
||||
public void afterStartup() throws UnknownHostException {
|
||||
remoteAddress = Inet4Address.getByName("10.0.0.102");
|
||||
thread.start();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void preDestroy() {
|
||||
stop = true;
|
||||
final KNXNetworkLinkIP copy = link;
|
||||
if (copy != null) {
|
||||
copy.close();
|
||||
}
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
private void run() {
|
||||
try {
|
||||
while (!stop) {
|
||||
if (link == null) {
|
||||
try {
|
||||
connect();
|
||||
} catch (KNXException e) {
|
||||
error(e);
|
||||
}
|
||||
} else {
|
||||
work();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
} finally {
|
||||
log.info("KNX Thread terminated.");
|
||||
}
|
||||
}
|
||||
|
||||
private void connect() throws KNXException, InterruptedException {
|
||||
log.debug("Connecting KNX link...");
|
||||
link = KNXNetworkLinkIP.newTunnelingLink(new InetSocketAddress("10.0.0.132", 0), new InetSocketAddress(remoteAddress, 3671), false, new TPSettings());
|
||||
link.addLinkListener(this);
|
||||
processCommunicator = new ProcessCommunicatorImpl(link);
|
||||
processCommunicator.addProcessListener(this);
|
||||
log.info("KNX link established.");
|
||||
}
|
||||
|
||||
private void work() throws InterruptedException {
|
||||
try {
|
||||
if (!knxGroupLinkService.sendNext(processCommunicator) && !knxGroupLinkService.readNext(processCommunicator)) {
|
||||
final ZonedDateTime nextTimestamp = knxGroupLinkService.getNextTimestamp();
|
||||
if (nextTimestamp == null) {
|
||||
doWait(0);
|
||||
} else {
|
||||
final long waitMs = Duration.between(ZonedDateTime.now(), nextTimestamp).toMillis();
|
||||
if (waitMs > 0) {
|
||||
doWait(waitMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (KNXException e) {
|
||||
error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void error(final KNXException e) throws InterruptedException {
|
||||
log.error(e.toString());
|
||||
cleanUp();
|
||||
doWait(ERROR_DELAY_MS);
|
||||
}
|
||||
|
||||
private void doWait(final long waitMs) throws InterruptedException {
|
||||
synchronized (lock) {
|
||||
log.debug("KNX Thread going to sleep{}...", waitMs > 0 ? " for " + waitMs + "ms" : "");
|
||||
if (waitMs > 0) {
|
||||
lock.wait(waitMs);
|
||||
} else {
|
||||
lock.wait();
|
||||
}
|
||||
log.debug("KNX Thread woke up.");
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanUp() {
|
||||
if (link != null) {
|
||||
link.close();
|
||||
link = null;
|
||||
processCommunicator = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyActionPending() {
|
||||
synchronized (lock) {
|
||||
lock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirmation(final FrameEvent e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void indication(final FrameEvent e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linkClosed(final CloseEvent e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupReadResponse(final ProcessEvent processEvent) {
|
||||
log.debug("{}", processEvent);
|
||||
knxGroupWriteService.updateOrCreate(processEvent.getDestination().getRawAddress(), processEvent.getASDU());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupWrite(final ProcessEvent processEvent) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void groupReadRequest(final ProcessEvent processEvent) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detached(final DetachEvent detachEvent) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
}
|
||||
24
src/main/java/de/ph87/homeautomation/knx/group/ComInfo.java
Normal file
24
src/main/java/de/ph87/homeautomation/knx/group/ComInfo.java
Normal file
@ -0,0 +1,24 @@
|
||||
package de.ph87.homeautomation.knx.group;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Embeddable
|
||||
public class ComInfo {
|
||||
|
||||
private boolean able = true;
|
||||
|
||||
private ZonedDateTime nextTimestamp = null;
|
||||
|
||||
private int errorCount = 0;
|
||||
|
||||
private String errorMessage = null;
|
||||
|
||||
}
|
||||
84
src/main/java/de/ph87/homeautomation/knx/group/KnxGroup.java
Normal file
84
src/main/java/de/ph87/homeautomation/knx/group/KnxGroup.java
Normal file
@ -0,0 +1,84 @@
|
||||
package de.ph87.homeautomation.knx.group;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import tuwien.auto.calimero.GroupAddress;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.Duration;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@Entity
|
||||
public class KnxGroup {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
@Setter(AccessLevel.NONE)
|
||||
private Long id;
|
||||
|
||||
@Column(unique = true)
|
||||
private int addressRaw;
|
||||
|
||||
@Column(unique = true)
|
||||
private String addressStr;
|
||||
|
||||
private String dpt;
|
||||
|
||||
private byte[] value;
|
||||
|
||||
private ZonedDateTime valueTimestamp;
|
||||
|
||||
private byte[] sendValue;
|
||||
|
||||
private int readInterval;
|
||||
|
||||
@Embedded
|
||||
private ComInfo read = new ComInfo();
|
||||
|
||||
@Embedded
|
||||
private ComInfo send = new ComInfo();
|
||||
|
||||
public void setAddress(final int rawAddress) {
|
||||
setAddress(new GroupAddress(rawAddress));
|
||||
}
|
||||
|
||||
public void setAddress(final int main, final int middle, final int sub) {
|
||||
setAddress(new GroupAddress(main, middle, sub));
|
||||
}
|
||||
|
||||
public void setAddress(final GroupAddress groupAddress) {
|
||||
this.addressRaw = groupAddress.getRawAddress();
|
||||
this.addressStr = groupAddress.toString();
|
||||
}
|
||||
|
||||
public GroupAddress getAddress() {
|
||||
return new GroupAddress(addressRaw);
|
||||
}
|
||||
|
||||
public void setReadInterval(final int readInterval) {
|
||||
if (readInterval <= 0) {
|
||||
this.readInterval = 0;
|
||||
} else {
|
||||
this.readInterval = readInterval;
|
||||
if (read.getNextTimestamp() == null || Duration.between(ZonedDateTime.now(), read.getNextTimestamp()).toSeconds() > this.readInterval) {
|
||||
updateNextReadTimestamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateNextReadTimestamp() {
|
||||
if (read.getErrorCount() == 0) {
|
||||
if (this.readInterval <= 0) {
|
||||
read.setNextTimestamp(null);
|
||||
} else {
|
||||
read.setNextTimestamp(ZonedDateTime.now().plusSeconds(read.getNextTimestamp() == null ? 0 : this.readInterval));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package de.ph87.homeautomation.knx.group;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import tuwien.auto.calimero.GroupAddress;
|
||||
import tuwien.auto.calimero.KNXException;
|
||||
import tuwien.auto.calimero.KNXFormatException;
|
||||
import tuwien.auto.calimero.datapoint.StateDP;
|
||||
import tuwien.auto.calimero.dptxlator.TranslatorTypes;
|
||||
import tuwien.auto.calimero.process.ProcessCommunicatorImpl;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class KnxGroupLinkService {
|
||||
|
||||
private final KnxGroupRepository knxGroupRepository;
|
||||
|
||||
public boolean sendNext(final ProcessCommunicatorImpl processCommunicator) throws KNXException {
|
||||
final Optional<KnxGroup> knxGroupOptional = knxGroupRepository.findFirstBySend_NextTimestampNotNullOrderBySend_NextTimestampAsc();
|
||||
if (knxGroupOptional.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return send(processCommunicator, knxGroupOptional.get());
|
||||
}
|
||||
|
||||
public boolean readNext(final ProcessCommunicatorImpl processCommunicator) throws KNXException, InterruptedException {
|
||||
final Optional<KnxGroup> knxGroupOptional = knxGroupRepository.findFirstByRead_NextTimestampLessThanEqualOrderByRead_NextTimestampAsc(ZonedDateTime.now());
|
||||
if (knxGroupOptional.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return read(processCommunicator, knxGroupOptional.get());
|
||||
}
|
||||
|
||||
private boolean send(final ProcessCommunicatorImpl processCommunicator, final KnxGroup knxGroup) throws KNXException {
|
||||
try {
|
||||
log.debug("Sending KnxGroup: {}", knxGroup);
|
||||
processCommunicator.write(knxGroup.getAddress(), TranslatorTypes.createTranslator(knxGroup.getDpt(), knxGroup.getSendValue()));
|
||||
knxGroup.getSend().setErrorCount(0);
|
||||
knxGroup.getSend().setErrorMessage(null);
|
||||
knxGroup.getSend().setNextTimestamp(null);
|
||||
log.debug("Successfully sent KnxGroup: {}", knxGroup);
|
||||
return true;
|
||||
} catch (KNXFormatException e) {
|
||||
log.error(e.toString());
|
||||
knxGroup.getSend().setErrorCount(knxGroup.getSend().getErrorCount() + 1);
|
||||
knxGroup.getSend().setErrorMessage(e.toString());
|
||||
knxGroup.getSend().setNextTimestamp(ZonedDateTime.now().plusSeconds(knxGroup.getSend().getErrorCount()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean read(final ProcessCommunicatorImpl processCommunicator, final KnxGroup knxGroup) throws KNXException, InterruptedException {
|
||||
try {
|
||||
log.debug("Reading KnxGroup: {}", knxGroup);
|
||||
processCommunicator.read(createStateDP(knxGroup));
|
||||
knxGroup.getRead().setErrorCount(0);
|
||||
knxGroup.getRead().setErrorMessage(null);
|
||||
return true;
|
||||
} catch (KNXFormatException e) {
|
||||
log.error(e.toString());
|
||||
knxGroup.getRead().setErrorCount(knxGroup.getRead().getErrorCount() + 1);
|
||||
knxGroup.getRead().setErrorMessage(e.toString());
|
||||
} finally {
|
||||
knxGroup.updateNextReadTimestamp();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private StateDP createStateDP(final KnxGroup knxGroup) {
|
||||
final GroupAddress groupAddress = knxGroup.getAddress();
|
||||
final int mainNumber = Integer.parseInt(knxGroup.getDpt().split("\\.", 2)[0]);
|
||||
return new StateDP(groupAddress, groupAddress.toString(), mainNumber, knxGroup.getDpt());
|
||||
}
|
||||
|
||||
public ZonedDateTime getNextTimestamp() {
|
||||
if (knxGroupRepository.findFirstBySend_NextTimestampNotNullOrderBySend_NextTimestampAsc().isPresent()) {
|
||||
return ZonedDateTime.now();
|
||||
}
|
||||
return knxGroupRepository.findFirstByRead_NextTimestampNotNullOrderByRead_NextTimestampAsc().map(KnxGroup::getRead).map(ComInfo::getNextTimestamp).orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package de.ph87.homeautomation.knx.group;
|
||||
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface KnxGroupRepository extends CrudRepository<KnxGroup, Long> {
|
||||
|
||||
Optional<KnxGroup> findByAddressRaw(int rawAddress);
|
||||
|
||||
List<KnxGroup> findAll();
|
||||
|
||||
Optional<KnxGroup> findFirstBySend_NextTimestampNotNullOrderBySend_NextTimestampAsc();
|
||||
|
||||
Optional<KnxGroup> findFirstByRead_NextTimestampLessThanEqualOrderByRead_NextTimestampAsc(ZonedDateTime timestamp);
|
||||
|
||||
List<KnxGroup> findAllByRead_AbleTrue();
|
||||
|
||||
Optional<KnxGroup> findFirstByRead_NextTimestampNotNullOrderByRead_NextTimestampAsc();
|
||||
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
package de.ph87.homeautomation.knx.group;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Transactional
|
||||
@RequiredArgsConstructor
|
||||
public class KnxGroupWriteService {
|
||||
|
||||
private final KnxGroupRepository knxGroupRepository;
|
||||
|
||||
public void updateOrCreate(final int rawAddress, final byte[] data) {
|
||||
final KnxGroup knxGroup = getOrCreate(rawAddress);
|
||||
knxGroup.setValue(data);
|
||||
knxGroup.setValueTimestamp(ZonedDateTime.now());
|
||||
log.debug("KnxGroup updated: {}", knxGroup);
|
||||
}
|
||||
|
||||
private KnxGroup getOrCreate(final int rawAddress) {
|
||||
return knxGroupRepository.findByAddressRaw(rawAddress).orElseGet(() -> {
|
||||
final KnxGroup trans = new KnxGroup();
|
||||
trans.setAddress(rawAddress);
|
||||
final KnxGroup saved = knxGroupRepository.save(trans);
|
||||
log.info("KnxGroup created: {}", saved);
|
||||
return saved;
|
||||
});
|
||||
}
|
||||
|
||||
public void markAllForRead() {
|
||||
knxGroupRepository.findAllByRead_AbleTrue().forEach(knxGroup -> knxGroup.getRead().setNextTimestamp(ZonedDateTime.now()));
|
||||
}
|
||||
|
||||
}
|
||||
17
src/main/resources/application.properties
Normal file
17
src/main/resources/application.properties
Normal file
@ -0,0 +1,17 @@
|
||||
logging.level.root=WARN
|
||||
logging.level.de.ph87=INFO
|
||||
#-
|
||||
spring.datasource.url=jdbc:h2:./Homeautomation;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=password
|
||||
#-
|
||||
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.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||
#-
|
||||
spring.jackson.serialization.indent_output=true
|
||||
#-
|
||||
spring.main.banner-mode=off
|
||||
Loading…
Reference in New Issue
Block a user