Homeautomation/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupWriteService.java

129 lines
5.5 KiB
Java

package de.ph87.homeautomation.knx.group;
import de.ph87.homeautomation.channel.ChannelChangedEvent;
import de.ph87.homeautomation.channel.ChannelDto;
import de.ph87.homeautomation.web.WebSocketService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tuwien.auto.calimero.GroupAddress;
import tuwien.auto.calimero.IndividualAddress;
import tuwien.auto.calimero.KNXException;
import tuwien.auto.calimero.KNXFormatException;
import tuwien.auto.calimero.dptxlator.*;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.function.Function;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class KnxGroupWriteService {
private final KnxGroupRepository knxGroupRepository;
private final ApplicationEventPublisher applicationEventPublisher;
private final WebSocketService webSocketService;
private final KnxGroupMapper knxGroupMapper;
public void requestRead(final KnxGroup knxGroup) {
knxGroup.getRead().setNextTimestamp(ZonedDateTime.now());
log.debug("Requesting read for KnxGroup: {}", knxGroup);
sendThreadWakeUpEvent();
}
public void requestWrite(final KnxGroup knxGroup, final double value) {
findTranslator(knxGroup).ifPresent(translator -> {
try {
if (translator instanceof DPTXlatorBoolean) {
((DPTXlatorBoolean) translator).setValue(value == 1.0);
} else if (translator instanceof DPTXlator8BitUnsigned) {
((DPTXlator8BitUnsigned) translator).setValue((int) value);
} else if (translator instanceof DPTXlatorSceneNumber) {
((DPTXlatorSceneNumber) translator).setValue((int) value - 1);
} else { // TODO implement all DPTXlator...
translator.setValue("" + value);
}
knxGroup.getSend().setNextTimestamp(ZonedDateTime.now());
knxGroup.setSendValue(translator.getData());
publish(knxGroup);
sendThreadWakeUpEvent();
} catch (KNXFormatException e) {
log.error("Failed set value \"{}\" to DptXlator {} for KnxGroup {}", value, translator, knxGroup);
}
});
}
public void setReceivedData(final GroupAddress groupAddress, final byte[] data, final IndividualAddress knxDeviceAddress) {
final Optional<KnxGroup> knxGroupOptional = knxGroupRepository.findByAddressRaw(groupAddress.getRawAddress());
if (knxGroupOptional.isEmpty()) {
log.error("No KnxGroup with address={}", groupAddress);
return;
}
final KnxGroup knxGroup = knxGroupOptional.get();
knxGroup.setLastTelegram(new KnxTelegram(data, ZonedDateTime.now(), knxDeviceAddress));
translate(knxGroup);
}
private void sendThreadWakeUpEvent() {
applicationEventPublisher.publishEvent(new KnxThreadWakeUpEvent());
}
private void translate(final KnxGroup knxGroup) {
findTranslator(knxGroup).ifPresent(translator -> {
translator.setData(knxGroup.getLastTelegram().getData());
final Optional<Double> valueOptional = translate(DPTXlatorBoolean.class, translator, DPTXlatorBoolean::getNumericValue)
.or(() -> translate(DPTXlator8BitUnsigned.class, translator, DPTXlator8BitUnsigned::getNumericValue))
.or(() -> translate(DPTXlator2ByteFloat.class, translator, DPTXlator2ByteFloat::getNumericValue))
.or(() -> translate(DPTXlator2ByteUnsigned.class, translator, DPTXlator2ByteUnsigned::getNumericValue))
.or(() -> translate(DPTXlator4ByteFloat.class, translator, DPTXlator4ByteFloat::getNumericValue))
.or(() -> translate(DPTXlator4ByteSigned.class, translator, DPTXlator4ByteSigned::getNumericValue))
.or(() -> translate(DPTXlator4ByteUnsigned.class, translator, DPTXlator4ByteUnsigned::getNumericValue))
.or(() -> translate(DPTXlator8BitSigned.class, translator, DPTXlator8BitSigned::getNumericValue))
.or(() -> translate(DPTXlator64BitSigned.class, translator, DPTXlator64BitSigned::getNumericValue))
.or(() -> translate(DPTXlatorSceneNumber.class, translator, DPTXlatorSceneNumber::getNumericValue));
// TODO implement all DPTXlator...
if (valueOptional.isPresent()) {
knxGroup.setValue(valueOptional.get());
knxGroup.setTimestamp(ZonedDateTime.now());
log.debug("KnxGroup updated: {}", knxGroup);
publish(knxGroup);
applicationEventPublisher.publishEvent(new ChannelChangedEvent(knxGroup));
} else {
log.error("Failed to get value from DptXlator {} for KnxGroup {}", translator, knxGroup);
}
});
}
private Optional<DPTXlator> findTranslator(final KnxGroup knxGroup) {
try {
return Optional.of(TranslatorTypes.createTranslator(knxGroup.getDptMain(), knxGroup.getDpt()));
} catch (KNXException e) {
log.error("No DptXlator found for KnxGroup: {}", knxGroup);
return Optional.empty();
}
}
private <Xlator extends DPTXlator, Value> Optional<Value> translate(final Class<Xlator> dptXlatorClass, final DPTXlator translator, final Function<Xlator, Value> getValueFromXlator) {
if (dptXlatorClass.isInstance(translator)) {
final Xlator castXlator = dptXlatorClass.cast(translator);
final Value value = getValueFromXlator.apply(castXlator);
return Optional.of(value);
}
return Optional.empty();
}
private KnxGroupDto publish(final KnxGroup knxGroup) {
final KnxGroupDto dto = knxGroupMapper.toDto(knxGroup);
webSocketService.send(ChannelDto.class.getSimpleName(), dto, true);
return dto;
}
}