[knx] FT12: Autodetect cEMI on Weinzierl devices (#14454)
Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>pull/14474/head
parent
1a01a0e021
commit
4f1dd5792f
|
@ -12,7 +12,11 @@
|
|||
*/
|
||||
package org.openhab.binding.knx.internal.client;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
@ -22,10 +26,12 @@ import org.openhab.core.thing.ThingUID;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import tuwien.auto.calimero.Connection.BlockingMode;
|
||||
import tuwien.auto.calimero.KNXException;
|
||||
import tuwien.auto.calimero.link.KNXNetworkLink;
|
||||
import tuwien.auto.calimero.link.KNXNetworkLinkFT12;
|
||||
import tuwien.auto.calimero.link.medium.TPSettings;
|
||||
import tuwien.auto.calimero.serial.FT12Connection;
|
||||
|
||||
/**
|
||||
* Serial specific {@link AbstractKNXClient} implementation.
|
||||
|
@ -54,21 +60,73 @@ public class SerialClient extends AbstractKNXClient {
|
|||
this.useCemi = useCemi;
|
||||
}
|
||||
|
||||
/**
|
||||
* try autodetection of cEMI devices via the PEI identification frame
|
||||
*
|
||||
* @implNote This is based on an vendor specific extension and may not work for other devices.
|
||||
*/
|
||||
protected boolean detectCemi() throws InterruptedException {
|
||||
final byte[] peiIdentifyReqFrame = { (byte) 0xa7 };
|
||||
final byte peiIdentifyCon = (byte) 0xa8;
|
||||
final byte peiWzIdentFrameLength = 11;
|
||||
|
||||
logger.trace("Checking for cEMI support");
|
||||
|
||||
try (FT12Connection serialConnection = new FT12Connection(serialPort)) {
|
||||
final CompletableFuture<byte[]> frameListener = new CompletableFuture<byte[]>();
|
||||
serialConnection.addConnectionListener(frameReceived -> {
|
||||
final byte[] content = frameReceived.getFrameBytes();
|
||||
if ((content.length > 0) && (content[0] == peiIdentifyCon)) {
|
||||
logger.trace("Received PEI confirmation of {} bytes", content.length);
|
||||
frameListener.complete(content);
|
||||
}
|
||||
});
|
||||
|
||||
serialConnection.send(peiIdentifyReqFrame, BlockingMode.NonBlocking);
|
||||
byte[] content = frameListener.get(1, TimeUnit.SECONDS);
|
||||
|
||||
if (peiWzIdentFrameLength == content.length) {
|
||||
// standard emi2 frame contain 9 bytes,
|
||||
// content[1..2] physical address
|
||||
// content[3..8] serial no
|
||||
//
|
||||
// Weinzierl adds 2 extra bytes, 0x0004 for capablity cEMI,
|
||||
// see "Weinzierl KNX BAOS Starter Kit, User Guide"
|
||||
if (0 == content[9] && 4 == content[10]) {
|
||||
logger.debug("Detected device with cEMI support");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (final ExecutionException | TimeoutException | KNXException na) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Exception detecting cEMI: ", na);
|
||||
}
|
||||
}
|
||||
|
||||
logger.trace("Did not detect device with cEMI support");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KNXNetworkLink establishConnection() throws KNXException, InterruptedException {
|
||||
try {
|
||||
logger.debug("Establishing connection to KNX bus through FT1.2 on serial port {}{}.", serialPort,
|
||||
(useCemi ? " using CEMI" : ""));
|
||||
boolean useCemiL = useCemi;
|
||||
if (!useCemiL) {
|
||||
useCemiL = detectCemi();
|
||||
}
|
||||
logger.debug("Establishing connection to KNX bus through FT1.2 on serial port {}{}{}", serialPort,
|
||||
(useCemiL ? " using cEMI" : ""), ((useCemiL != useCemi) ? " (autodetected)" : ""));
|
||||
// CEMI support by Calimero library, userful for newer serial devices like KNX RF sticks, kBerry,
|
||||
// etc.; default is still old EMI frame format
|
||||
if (useCemi) {
|
||||
if (useCemiL) {
|
||||
return KNXNetworkLinkFT12.newCemiLink(serialPort, new TPSettings());
|
||||
}
|
||||
|
||||
return new KNXNetworkLinkFT12(serialPort, new TPSettings());
|
||||
|
||||
} catch (NoClassDefFoundError e) {
|
||||
throw new KNXException(
|
||||
"The serial FT1.2 KNX connection requires the RXTX libraries to be available, but they could not be found!",
|
||||
"The serial FT1.2 KNX connection requires the serial libraries to be available, but they could not be found!",
|
||||
e);
|
||||
} catch (KNXException e) {
|
||||
final String msg = e.getMessage();
|
||||
|
|
Loading…
Reference in New Issue