[knx] FT12: Autodetect cEMI on Weinzierl devices (#14454)
Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>
This commit is contained in:
parent
1a01a0e021
commit
4f1dd5792f
@ -12,7 +12,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.knx.internal.client;
|
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.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
@ -22,10 +26,12 @@ import org.openhab.core.thing.ThingUID;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import tuwien.auto.calimero.Connection.BlockingMode;
|
||||||
import tuwien.auto.calimero.KNXException;
|
import tuwien.auto.calimero.KNXException;
|
||||||
import tuwien.auto.calimero.link.KNXNetworkLink;
|
import tuwien.auto.calimero.link.KNXNetworkLink;
|
||||||
import tuwien.auto.calimero.link.KNXNetworkLinkFT12;
|
import tuwien.auto.calimero.link.KNXNetworkLinkFT12;
|
||||||
import tuwien.auto.calimero.link.medium.TPSettings;
|
import tuwien.auto.calimero.link.medium.TPSettings;
|
||||||
|
import tuwien.auto.calimero.serial.FT12Connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serial specific {@link AbstractKNXClient} implementation.
|
* Serial specific {@link AbstractKNXClient} implementation.
|
||||||
@ -54,21 +60,73 @@ public class SerialClient extends AbstractKNXClient {
|
|||||||
this.useCemi = useCemi;
|
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
|
@Override
|
||||||
protected KNXNetworkLink establishConnection() throws KNXException, InterruptedException {
|
protected KNXNetworkLink establishConnection() throws KNXException, InterruptedException {
|
||||||
try {
|
try {
|
||||||
logger.debug("Establishing connection to KNX bus through FT1.2 on serial port {}{}.", serialPort,
|
boolean useCemiL = useCemi;
|
||||||
(useCemi ? " using CEMI" : ""));
|
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,
|
// CEMI support by Calimero library, userful for newer serial devices like KNX RF sticks, kBerry,
|
||||||
// etc.; default is still old EMI frame format
|
// etc.; default is still old EMI frame format
|
||||||
if (useCemi) {
|
if (useCemiL) {
|
||||||
return KNXNetworkLinkFT12.newCemiLink(serialPort, new TPSettings());
|
return KNXNetworkLinkFT12.newCemiLink(serialPort, new TPSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new KNXNetworkLinkFT12(serialPort, new TPSettings());
|
return new KNXNetworkLinkFT12(serialPort, new TPSettings());
|
||||||
|
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
throw new KNXException(
|
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);
|
e);
|
||||||
} catch (KNXException e) {
|
} catch (KNXException e) {
|
||||||
final String msg = e.getMessage();
|
final String msg = e.getMessage();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user