110 lines
4.7 KiB
Java
110 lines
4.7 KiB
Java
package de.ph87.homeautomation.knx.group;
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import tuwien.auto.calimero.GroupAddress;
|
|
import tuwien.auto.calimero.KNXException;
|
|
import tuwien.auto.calimero.KNXFormatException;
|
|
import tuwien.auto.calimero.KNXTimeoutException;
|
|
import tuwien.auto.calimero.datapoint.StateDP;
|
|
import tuwien.auto.calimero.dptxlator.TranslatorTypes;
|
|
import tuwien.auto.calimero.process.ProcessCommunicatorImpl;
|
|
|
|
import java.time.ZonedDateTime;
|
|
import java.util.Optional;
|
|
|
|
@Slf4j
|
|
@Service
|
|
@Transactional
|
|
@RequiredArgsConstructor
|
|
public class KnxGroupLinkService {
|
|
|
|
public static final long ERROR_DELAY_FACTOR = 500 * 1000 * 1000L;
|
|
|
|
private final KnxGroupRepository knxGroupRepository;
|
|
|
|
public boolean sendNext(final ProcessCommunicatorImpl processCommunicator) throws KNXException {
|
|
final Optional<KnxGroup> nextOptional = knxGroupRepository.findFirstBySend_NextTimestampNotNullOrderBySend_NextTimestampAsc();
|
|
if (nextOptional.isEmpty()) {
|
|
return false;
|
|
}
|
|
return send(processCommunicator, nextOptional.get());
|
|
}
|
|
|
|
public boolean readNext(final ProcessCommunicatorImpl processCommunicator) throws KNXException, InterruptedException {
|
|
final Optional<KnxGroup> nextOptional = knxGroupRepository.findFirstByRead_NextTimestampLessThanEqualOrderByRead_NextTimestampAsc(ZonedDateTime.now());
|
|
if (nextOptional.isEmpty()) {
|
|
return false;
|
|
}
|
|
return read(processCommunicator, nextOptional.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.getDptMain(), knxGroup.getDptSub(), knxGroup.getSendValue()));
|
|
if (knxGroup.getSend().getErrorCount() > 0) {
|
|
log.info("KnxGroup recovered from send-error: {}", knxGroup);
|
|
}
|
|
knxGroup.getSend().setErrorCount(0);
|
|
knxGroup.getSend().setErrorMessage(null);
|
|
knxGroup.getSend().setNextTimestamp(null);
|
|
log.debug("Successfully sent KnxGroup: {}", knxGroup);
|
|
return true;
|
|
} catch (KNXTimeoutException | KNXFormatException e) {
|
|
log.error("Failed to send KnxGroup {}", knxGroup);
|
|
knxGroup.getSend().setErrorCount(knxGroup.getSend().getErrorCount() + 1);
|
|
knxGroup.getSend().setErrorMessage(e.getMessage());
|
|
knxGroup.getSend().setNextTimestamp(ZonedDateTime.now().plusNanos(knxGroup.getSend().getErrorCount() * knxGroup.getSend().getErrorCount() * ERROR_DELAY_FACTOR));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean read(final ProcessCommunicatorImpl processCommunicator, final KnxGroup knxGroup) throws KNXException, InterruptedException {
|
|
try {
|
|
log.debug("Reading KnxGroup: {}", knxGroup);
|
|
processCommunicator.read(createStateDP(knxGroup));
|
|
if (knxGroup.getRead().getErrorCount() > 0) {
|
|
log.info("KnxGroup recovered from read-error: {}", knxGroup);
|
|
}
|
|
knxGroup.getRead().setErrorCount(0);
|
|
knxGroup.getRead().setErrorMessage(null);
|
|
knxGroup.getRead().setNextTimestamp(null);
|
|
log.debug("Successfully sent KnxGroup: {}", knxGroup);
|
|
return true;
|
|
} catch (KNXTimeoutException | KNXFormatException e) {
|
|
log.error("Failed to read KnxGroup {}", knxGroup);
|
|
knxGroup.getRead().setErrorCount(knxGroup.getRead().getErrorCount() + 1);
|
|
knxGroup.getRead().setErrorMessage(e.getMessage());
|
|
knxGroup.getRead().setNextTimestamp(ZonedDateTime.now().plusNanos(knxGroup.getRead().getErrorCount() * knxGroup.getRead().getErrorCount() * ERROR_DELAY_FACTOR));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private StateDP createStateDP(final KnxGroup knxGroup) {
|
|
final GroupAddress groupAddress = knxGroup.getAddress();
|
|
return new StateDP(groupAddress, groupAddress.toString(), knxGroup.getDptMain(), knxGroup.getDpt());
|
|
}
|
|
|
|
public ZonedDateTime getNextTimestamp() {
|
|
final Optional<ZonedDateTime> sendOptional = knxGroupRepository.findFirstBySend_NextTimestampNotNullOrderBySend_NextTimestampAsc().map(KnxGroup::getSend).map(KnxGroupLinkInfo::getNextTimestamp);
|
|
final Optional<ZonedDateTime> readOptional = knxGroupRepository.findFirstByRead_NextTimestampNotNullOrderByRead_NextTimestampAsc().map(KnxGroup::getRead).map(KnxGroupLinkInfo::getNextTimestamp);
|
|
if (sendOptional.isEmpty()) {
|
|
return readOptional.orElse(null);
|
|
}
|
|
final ZonedDateTime send = sendOptional.get();
|
|
if (readOptional.isEmpty()) {
|
|
return send;
|
|
}
|
|
final ZonedDateTime read = readOptional.get();
|
|
if (send.isBefore(read)) {
|
|
return send;
|
|
}
|
|
return read;
|
|
|
|
}
|
|
|
|
}
|