2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.knx.internal.client;
15 import java.util.HashSet;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.core.util.HexUtils;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
23 import tuwien.auto.calimero.FrameEvent;
24 import tuwien.auto.calimero.IndividualAddress;
25 import tuwien.auto.calimero.KNXAddress;
26 import tuwien.auto.calimero.KNXTimeoutException;
27 import tuwien.auto.calimero.Priority;
28 import tuwien.auto.calimero.cemi.CEMILData;
29 import tuwien.auto.calimero.link.KNXLinkClosedException;
30 import tuwien.auto.calimero.link.KNXNetworkLink;
31 import tuwien.auto.calimero.link.NetworkLinkListener;
32 import tuwien.auto.calimero.link.medium.KNXMediumSettings;
35 * This class provides a simulated KNXNetworkLink with test stubs for integration tests.
37 * See Calimero documentation, calimero-ng.pdf.
39 * Frames sent via {@link #sendRequest()} and {@link sendRequestWait()} will be looped back
40 * to all registered listeners. {@link #getLastFrame()} will return the binary data provided
41 * to the last send command.
43 * @author Holger Friedrich - Initial contribution
46 public class DummyKNXNetworkLink implements KNXNetworkLink {
47 public static final Logger LOGGER = LoggerFactory.getLogger(DummyKNXNetworkLink.class);
48 public static final int GROUP_WRITE = 0x80;
50 private byte[] lastFrame = new byte[0];
51 private Set<NetworkLinkListener> listeners = new HashSet<>();
53 public void setKNXMedium(KNXMediumSettings settings) {
54 LOGGER.warn(settings.toString());
57 public KNXMediumSettings getKNXMedium() {
58 return KNXMediumSettings.create(KNXMediumSettings.MEDIUM_TP1, new IndividualAddress(1, 2, 3));
61 public void addLinkListener(NetworkLinkListener l) {
65 public void removeLinkListener(NetworkLinkListener l) {
69 public void setHopCount(int count) {
72 public int getHopCount() {
76 public void sendRequest(KNXAddress dst, Priority p, byte[] nsdu)
77 throws KNXTimeoutException, KNXLinkClosedException {
78 sendRequestWait(dst, p, nsdu);
81 public void sendRequestWait(KNXAddress dst, Priority p, byte[] nsdu)
82 throws KNXTimeoutException, KNXLinkClosedException {
83 LOGGER.info("sendRequestWait() {} {} {}", dst, p, HexUtils.bytesToHex(nsdu, " "));
85 lastFrame = nsdu.clone();
87 // not we want to mimic a received frame by looping it back to all listeners
90 * relevant steps to create a CEMI frame needed for triggering a frame event:
92 * final CEMILData f = (CEMILData) e.getFrame();
93 * final var apdu = f.getPayload();
94 * final int svc = DataUnitBuilder.getAPDUService(apdu);
96 * fireGroupReadWrite(f, DataUnitBuilder.extractASDU(apdu), svc, apdu.length <= 2);
97 * send(CEMILData.MC_LDATA_IND, dst, p, nsdu, true);
99 int service = GROUP_WRITE;
100 byte[] apdu = new byte[nsdu.length + 2];
101 apdu[0] = (byte) (service >> 8);
102 apdu[1] = (byte) service;
103 System.arraycopy(nsdu, 0, apdu, 2, nsdu.length);
105 final IndividualAddress src = new IndividualAddress(1, 1, 1);
106 final boolean repeat = false;
107 final int hopCount = 1;
109 FrameEvent f = new FrameEvent(this, new CEMILData(CEMILData.MC_LDATA_IND, src, dst, nsdu, p, repeat, hopCount));
111 listeners.forEach(listener -> {
112 listener.indication(f);
116 public void send(CEMILData msg, boolean waitForCon) throws KNXTimeoutException, KNXLinkClosedException {
117 LOGGER.warn("send() not implemented");
120 public String getName() {
124 public boolean isOpen() {
128 public void close() {
131 public byte[] getLastFrame() {