calimero-project / calimero-core

Core library for KNX network access and management
Other
126 stars 64 forks source link

KNXNetworkLinkFT12: detect status, CEMI setting.... #116

Closed holgerfriedrich closed 1 year ago

holgerfriedrich commented 1 year ago

Hi @bmalinowsky! This is not a bug report, but more or less a support request.

We use KNXNetworkLinkFT12(...) or KNXNetworkLinkFT12::newCemiLink(...) to open a serial connection, depending on user setting for CEMI. With a CEMI device like the kBerry, communication works only with CEMI. Without CEMI, the code does not throw exceptions; we just see no packets coming in. Is there an API function which could detect wrong CEMI setting? Maybe I have overlooked something....

bmalinowsky commented 1 year ago

No, the FT1.2 transmission protocol itself is not concerned with KNX.

For Weinzierl, you can try the following utility:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import tuwien.auto.calimero.Connection.BlockingMode;
import tuwien.auto.calimero.KNXException;
import tuwien.auto.calimero.serial.FT12Connection;

/**
 * PEI check for Weinzierl FT1.2 cEMI support.
 * Compile-time jar deps: calimero-core, calimero-rxtx+nrjavaserial, slf4j-api
 */
public final class WeinzierlFt12CemiSupport {
    private static final int peiIdentifyReq = 0xa7;
    private static final int peiIdentifyCon = 0xa8;

    public static void main(final String[] args) throws KNXException, InterruptedException, TimeoutException {
        if (args.length == 0)
            System.err.println("supply FT1.2 communication port identifier");
        else
            System.out.println(supportsCemi(args[0]));
    }

    public static boolean supportsCemi(final String portId)
            throws KNXException, InterruptedException, TimeoutException {
        try (var conn = new FT12Connection(portId)) {
            final var cemi = new CompletableFuture<Boolean>();
            conn.addConnectionListener(frameEvent -> {
                final var frame = frameEvent.getFrameBytes();
                if ((frame[0] & 0xff) == peiIdentifyCon) {
                    // PEI_identify.con is 9 bytes, Weinzierl cEMI support is indicated by 2 extra bytes
                    cemi.complete(frame.length == 11);
                }
            });

            conn.send(new byte[] { (byte) peiIdentifyReq }, BlockingMode.NonBlocking);
            return cemi.get(1, TimeUnit.SECONDS);
        }
        catch (final ExecutionException na) { throw new AssertionError(); }
    }
}
holgerfriedrich commented 1 year ago

Thank you @bmalinowsky, I will check if I can make use of this.