2 * Copyright (c) 2010-2022 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.nio.ByteBuffer;
16 import java.text.MessageFormat;
17 import java.util.concurrent.TimeUnit;
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
24 import tuwien.auto.calimero.IndividualAddress;
25 import tuwien.auto.calimero.KNXException;
26 import tuwien.auto.calimero.mgmt.Destination;
27 import tuwien.auto.calimero.mgmt.ManagementClient;
30 * Client for retrieving additional device descriptions.
32 * @author Simon Kaufmann - initial contribution and API.
36 public class DeviceInfoClientImpl implements DeviceInfoClient {
38 private final Logger logger = LoggerFactory.getLogger(DeviceInfoClientImpl.class);
39 private final ManagementClient managementClient;
41 DeviceInfoClientImpl(ManagementClient managementClient) {
42 this.managementClient = managementClient;
46 private interface ReadFunction<T, R> {
48 R apply(T t) throws KNXException, InterruptedException;
51 private byte @Nullable [] readFromManagementClient(String task, long timeout, IndividualAddress address,
52 ReadFunction<Destination, byte[]> function) {
53 final long start = System.nanoTime();
54 while ((System.nanoTime() - start) < TimeUnit.MILLISECONDS.toNanos(timeout)) {
55 Destination destination = null;
57 logger.trace("Going to {} of {} ", task, address);
58 destination = managementClient.createDestination(address, true);
59 byte[] result = function.apply(destination);
60 logger.trace("Finished to {} of {}, result: {}", task, address, result == null ? null : result.length);
62 } catch (KNXException e) {
63 logger.debug("Could not {} of {}: {}", task, address, e.getMessage());
64 } catch (InterruptedException e) {
65 logger.trace("Interrupted to {}", task);
68 if (destination != null) {
69 destination.destroy();
76 private void authorize(boolean authenticate, Destination destination) throws KNXException, InterruptedException {
78 managementClient.authorize(destination, (ByteBuffer.allocate(4)).put((byte) 0xFF).put((byte) 0xFF)
79 .put((byte) 0xFF).put((byte) 0xFF).array());
84 public synchronized byte @Nullable [] readDeviceDescription(IndividualAddress address, int descType,
85 boolean authenticate, long timeout) {
86 String task = "read the device description";
87 return readFromManagementClient(task, timeout, address, destination -> {
88 authorize(authenticate, destination);
89 return managementClient.readDeviceDesc(destination, descType);
94 public synchronized byte @Nullable [] readDeviceMemory(IndividualAddress address, int startAddress, int bytes,
95 boolean authenticate, long timeout) {
96 String task = MessageFormat.format("read {0} bytes at memory location {1}", bytes, startAddress);
97 return readFromManagementClient(task, timeout, address, destination -> {
98 authorize(authenticate, destination);
99 return managementClient.readMemory(destination, startAddress, bytes);
104 public synchronized byte @Nullable [] readDeviceProperties(IndividualAddress address,
105 final int interfaceObjectIndex, final int propertyId, final int start, final int elements,
106 boolean authenticate, long timeout) {
107 String task = MessageFormat.format("read device property {0} at index {1}", propertyId, interfaceObjectIndex);
108 return readFromManagementClient(task, timeout, address, destination -> {
109 authorize(authenticate, destination);
110 return managementClient.readProperty(destination, interfaceObjectIndex, propertyId, start, elements);
115 public boolean isConnected() {
116 return managementClient.isOpen();