129 lines
5.5 KiB
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;
|
|
}
|
|
|
|
}
|