[knx] Improve reading of device properties (#14050)
* [knx] Improve reading of device properties * [knx] DD2 logging only in debug mode Signed-off-by: Holger Friedrich <mail@holger-friedrich.de>
This commit is contained in:
parent
7ec7de55e3
commit
7bd99df364
|
@ -38,13 +38,16 @@ public class KNXBindingConstants {
|
|||
public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device");
|
||||
|
||||
// Property IDs
|
||||
public static final String FIRMWARE_TYPE = "firmwaretype";
|
||||
public static final String FIRMWARE_VERSION = "firmwareversion";
|
||||
public static final String FIRMWARE_SUBVERSION = "firmwaresubversion";
|
||||
public static final String MANUFACTURER_NAME = "manfacturername";
|
||||
public static final String MANUFACTURER_SERIAL_NO = "manfacturerserialnumber";
|
||||
public static final String MANUFACTURER_HARDWARE_TYPE = "manfacturerhardwaretype";
|
||||
public static final String MANUFACTURER_FIRMWARE_REVISION = "manfacturerfirmwarerevision";
|
||||
public static final String DEVICE_MASK_VERSION = "deviceMaskVersion";
|
||||
public static final String DEVICE_PROFILE = "deviceProfile";
|
||||
public static final String DEVICE_MEDIUM_TYPE = "deviceMediumType";
|
||||
public static final String FRIENDLY_NAME = "deviceName";
|
||||
public static final String MANUFACTURER_NAME = "manufacturerName";
|
||||
public static final String MANUFACTURER_SERIAL_NO = "manufacturerSerialNumber";
|
||||
public static final String MANUFACTURER_HARDWARE_TYPE = "manufacturerHardwareType";
|
||||
public static final String MANUFACTURER_FIRMWARE_REVISION = "manufacturerFirmwareRevision";
|
||||
public static final String MANUFACTURER_ORDER_INFO = "manufacturerOrderInfo";
|
||||
public static final String MAX_APDU_LENGTH = "maxApduLength";
|
||||
|
||||
// Thing Configuration parameters
|
||||
public static final String IP_ADDRESS = "ipAddress";
|
||||
|
|
|
@ -26,14 +26,15 @@ import tuwien.auto.calimero.IndividualAddress;
|
|||
@NonNullByDefault
|
||||
public interface DeviceInfoClient {
|
||||
|
||||
byte @Nullable [] readDeviceDescription(IndividualAddress address, int descType, boolean authenticate,
|
||||
long timeout);
|
||||
byte @Nullable [] readDeviceDescription(IndividualAddress address, int descType, boolean authenticate, long timeout)
|
||||
throws InterruptedException;
|
||||
|
||||
byte @Nullable [] readDeviceMemory(IndividualAddress address, int startAddress, int bytes, boolean authenticate,
|
||||
long timeout);
|
||||
long timeout) throws InterruptedException;
|
||||
|
||||
byte @Nullable [] readDeviceProperties(IndividualAddress address, final int interfaceObjectIndex,
|
||||
final int propertyId, final int start, final int elements, boolean authenticate, long timeout);
|
||||
final int propertyId, final int start, final int elements, boolean authenticate, long timeout)
|
||||
throws InterruptedException;
|
||||
|
||||
public boolean isConnected();
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class DeviceInfoClientImpl implements DeviceInfoClient {
|
|||
}
|
||||
|
||||
private byte @Nullable [] readFromManagementClient(String task, long timeout, IndividualAddress address,
|
||||
ReadFunction<Destination, byte[]> function) {
|
||||
ReadFunction<Destination, byte[]> function) throws InterruptedException {
|
||||
final long start = System.nanoTime();
|
||||
while ((System.nanoTime() - start) < TimeUnit.MILLISECONDS.toNanos(timeout)) {
|
||||
Destination destination = null;
|
||||
|
@ -68,7 +68,7 @@ public class DeviceInfoClientImpl implements DeviceInfoClient {
|
|||
}
|
||||
} catch (InterruptedException e) {
|
||||
logger.trace("Interrupted to {}", task);
|
||||
return null;
|
||||
throw e;
|
||||
} finally {
|
||||
if (destination != null) {
|
||||
destination.destroy();
|
||||
|
@ -87,7 +87,7 @@ public class DeviceInfoClientImpl implements DeviceInfoClient {
|
|||
|
||||
@Override
|
||||
public synchronized byte @Nullable [] readDeviceDescription(IndividualAddress address, int descType,
|
||||
boolean authenticate, long timeout) {
|
||||
boolean authenticate, long timeout) throws InterruptedException {
|
||||
String task = "read the device description";
|
||||
return readFromManagementClient(task, timeout, address, destination -> {
|
||||
authorize(authenticate, destination);
|
||||
|
@ -97,7 +97,7 @@ public class DeviceInfoClientImpl implements DeviceInfoClient {
|
|||
|
||||
@Override
|
||||
public synchronized byte @Nullable [] readDeviceMemory(IndividualAddress address, int startAddress, int bytes,
|
||||
boolean authenticate, long timeout) {
|
||||
boolean authenticate, long timeout) throws InterruptedException {
|
||||
String task = MessageFormat.format("read {0} bytes at memory location {1}", bytes, startAddress);
|
||||
return readFromManagementClient(task, timeout, address, destination -> {
|
||||
authorize(authenticate, destination);
|
||||
|
@ -108,7 +108,7 @@ public class DeviceInfoClientImpl implements DeviceInfoClient {
|
|||
@Override
|
||||
public synchronized byte @Nullable [] readDeviceProperties(IndividualAddress address,
|
||||
final int interfaceObjectIndex, final int propertyId, final int start, final int elements,
|
||||
boolean authenticate, long timeout) {
|
||||
boolean authenticate, long timeout) throws InterruptedException {
|
||||
String task = MessageFormat.format("read device property {0} at index {1}", propertyId, interfaceObjectIndex);
|
||||
return readFromManagementClient(task, timeout, address, destination -> {
|
||||
authorize(authenticate, destination);
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.util.Set;
|
|||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.knx.internal.handler.Firmware;
|
||||
import org.openhab.binding.knx.internal.handler.Manufacturer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -30,14 +29,17 @@ import org.slf4j.LoggerFactory;
|
|||
import tuwien.auto.calimero.DataUnitBuilder;
|
||||
import tuwien.auto.calimero.DeviceDescriptor;
|
||||
import tuwien.auto.calimero.DeviceDescriptor.DD0;
|
||||
import tuwien.auto.calimero.DeviceDescriptor.DD2;
|
||||
import tuwien.auto.calimero.GroupAddress;
|
||||
import tuwien.auto.calimero.IndividualAddress;
|
||||
import tuwien.auto.calimero.KNXIllegalArgumentException;
|
||||
import tuwien.auto.calimero.mgmt.PropertyAccess.PID;
|
||||
|
||||
/**
|
||||
* Client dedicated to read device specific information using the {@link DeviceInfoClient}.
|
||||
*
|
||||
* @author Simon Kaufmann - initial contribution and API.
|
||||
* @author Holger Friedrich - support additional device properties
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
|
@ -78,6 +80,15 @@ public class DeviceInspector {
|
|||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link readDeviceInfo} tries to read information from the KNX device.
|
||||
* This function catches {@link java.lang.InterruptedException}. It can safely be cancelled.
|
||||
*
|
||||
* The number of properties returned by this function depends on the data provided
|
||||
* by the KNX device.
|
||||
*
|
||||
* @return List of device properties
|
||||
*/
|
||||
@Nullable
|
||||
public Result readDeviceInfo() {
|
||||
if (!getClient().isConnected()) {
|
||||
|
@ -86,14 +97,29 @@ public class DeviceInspector {
|
|||
|
||||
logger.debug("Fetching device information for address {}", address);
|
||||
Map<String, String> properties = new HashMap<>();
|
||||
try {
|
||||
properties.putAll(readDeviceDescription(address));
|
||||
properties.putAll(readDeviceProperties(address));
|
||||
} catch (InterruptedException e) {
|
||||
final String msg = e.getMessage();
|
||||
logger.debug("Interrupted while fetching the device description for a device '{}' {}", address,
|
||||
msg != null ? ": " + msg : "");
|
||||
}
|
||||
return new Result(properties, Collections.emptySet());
|
||||
}
|
||||
|
||||
private Map<String, String> readDeviceProperties(IndividualAddress address) {
|
||||
/**
|
||||
* @implNote {@link readDeviceProperties(address)} tries to read several properties from the KNX device.
|
||||
* Errors reading single properties are ignored, the respective item is skipped and readout continues
|
||||
* with next property. {@link java.lang.InterruptedException} is thrown to allow for stopping the readout
|
||||
* task immediately on connection loss or thing deconstruction.
|
||||
*
|
||||
* @param address Individual address of KNX device
|
||||
* @return List of device properties
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private Map<String, String> readDeviceProperties(IndividualAddress address) throws InterruptedException {
|
||||
Map<String, String> ret = new HashMap<>();
|
||||
try {
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
// check if there is a Device Object in the KNX device
|
||||
byte[] elements = getClient().readDeviceProperties(address, DEVICE_OBJECT, PID.OBJECT_TYPE, 0, 1, false,
|
||||
|
@ -102,15 +128,137 @@ public class DeviceInspector {
|
|||
Thread.sleep(OPERATION_INTERVAL);
|
||||
String manufacturerID = Manufacturer.getName(toUnsigned(getClient().readDeviceProperties(address,
|
||||
DEVICE_OBJECT, PID.MANUFACTURER_ID, 1, 1, false, OPERATION_TIMEOUT)));
|
||||
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
String serialNo = toHex(getClient().readDeviceProperties(address, DEVICE_OBJECT, PID.SERIAL_NUMBER, 1,
|
||||
1, false, OPERATION_TIMEOUT), "");
|
||||
String serialNo = toHex(getClient().readDeviceProperties(address, DEVICE_OBJECT, PID.SERIAL_NUMBER, 1, 1,
|
||||
false, OPERATION_TIMEOUT), "");
|
||||
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
String hardwareType = toHex(getClient().readDeviceProperties(address, DEVICE_OBJECT, HARDWARE_TYPE, 1,
|
||||
1, false, OPERATION_TIMEOUT), " ");
|
||||
String hardwareType = toHex(getClient().readDeviceProperties(address, DEVICE_OBJECT, HARDWARE_TYPE, 1, 1,
|
||||
false, OPERATION_TIMEOUT), " ");
|
||||
|
||||
// PID_FIRMWARE_REVISION, optional, fallback PID_VERSION according to spec
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
String firmwareRevision = Integer.toString(toUnsigned(getClient().readDeviceProperties(address,
|
||||
DEVICE_OBJECT, PID.FIRMWARE_REVISION, 1, 1, false, OPERATION_TIMEOUT)));
|
||||
String firmwareRevision = null;
|
||||
try {
|
||||
byte[] result = getClient().readDeviceProperties(address, DEVICE_OBJECT, PID.FIRMWARE_REVISION, 1, 1,
|
||||
false, OPERATION_TIMEOUT);
|
||||
if (result != null) {
|
||||
firmwareRevision = Integer.toString(toUnsigned(result));
|
||||
} else {
|
||||
// try fallback to PID_VERSION
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
result = getClient().readDeviceProperties(address, DEVICE_OBJECT, PID.VERSION, 1, 1, false,
|
||||
OPERATION_TIMEOUT);
|
||||
if (result != null) {
|
||||
// data format is DPT217.001
|
||||
int i = toUnsigned(result);
|
||||
firmwareRevision = Integer.toString((i & 0xF800) >> 11) + "."
|
||||
+ Integer.toString((i & 0x07C0) >> 6) + "." + Integer.toString((i & 0x003F));
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw e;
|
||||
} catch (Exception ignore) {
|
||||
// allowed to fail, optional
|
||||
}
|
||||
|
||||
// MAX_APDU_LENGTH, for *routing*, optional, fallback to MAX_APDU_LENGTH of device
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
String maxApdu = "";
|
||||
try {
|
||||
byte[] result = getClient().readDeviceProperties(address, DEVICE_OBJECT, PID.MAX_APDULENGTH, 1, 1,
|
||||
false, OPERATION_TIMEOUT);
|
||||
if (result != null) {
|
||||
maxApdu = Integer.toString(toUnsigned(result));
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw e;
|
||||
} catch (Exception ignore) {
|
||||
// allowed to fail, optional
|
||||
}
|
||||
if (!maxApdu.isEmpty()) {
|
||||
logger.trace("Max APDU of device {} is {} bytes (routing)", address, maxApdu);
|
||||
} else {
|
||||
// fallback: MAX_APDU_LENGTH; if availble set the default is 14 according to spec
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
try {
|
||||
byte[] result = getClient().readDeviceProperties(address, ADDRESS_TABLE_OBJECT,
|
||||
MAX_ROUTED_APDU_LENGTH, 1, 1, false, OPERATION_TIMEOUT);
|
||||
if (result != null) {
|
||||
maxApdu = Integer.toString(toUnsigned(result));
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw e;
|
||||
} catch (Exception ignore) {
|
||||
// allowed to fail, optional
|
||||
}
|
||||
if (!maxApdu.isEmpty()) {
|
||||
logger.trace("Max APDU of device {} is {} bytes", address, maxApdu);
|
||||
} else {
|
||||
logger.trace("Max APDU of device {} not set, fallback to 14 bytes", address);
|
||||
maxApdu = "14"; // see spec
|
||||
}
|
||||
}
|
||||
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
byte[] orderInfo = getClient().readDeviceProperties(address, DEVICE_OBJECT, PID.ORDER_INFO, 1, 1, false,
|
||||
OPERATION_TIMEOUT);
|
||||
if (orderInfo != null) {
|
||||
final String hexString = toHex(orderInfo, "");
|
||||
if (!"ffffffffffffffffffff".equals(hexString) && !"00000000000000000000".equals(hexString)) {
|
||||
String result = new String(orderInfo);
|
||||
result = result.trim();
|
||||
if (result.isEmpty()) {
|
||||
result = "0x" + hexString;
|
||||
} else {
|
||||
final String printable = result.replaceAll("[^\\x20-\\x7E]", ".");
|
||||
if (!printable.equals(result)) {
|
||||
result = printable + " (0x" + hexString + ")";
|
||||
}
|
||||
}
|
||||
logger.trace("Order code of device {} is \"{}\"", address, result);
|
||||
ret.put(MANUFACTURER_ORDER_INFO, result);
|
||||
}
|
||||
}
|
||||
|
||||
// read FRIENDLY_NAME, optional
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
try {
|
||||
byte[] count = getClient().readDeviceProperties(address, ROUTER_OBJECT, PID.FRIENDLY_NAME, 0, 1, false,
|
||||
OPERATION_TIMEOUT);
|
||||
if ((count != null) && (toUnsigned(count) == 30)) {
|
||||
StringBuffer buf = new StringBuffer(30);
|
||||
for (int i = 1; i <= 30; i++) {
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
// for some reason, reading more than one character per message fails
|
||||
// reading only one character is inefficient, but works
|
||||
byte[] data = getClient().readDeviceProperties(address, ROUTER_OBJECT, PID.FRIENDLY_NAME, i, 1,
|
||||
false, OPERATION_TIMEOUT);
|
||||
if (toUnsigned(data) != 0) {
|
||||
if (data != null) {
|
||||
buf.append(new String(data));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
final String result = buf.toString();
|
||||
if (result.matches("^[\\x20-\\x7E]+$")) {
|
||||
logger.debug("Identified device {} as \"{}\"", address, result);
|
||||
ret.put(FRIENDLY_NAME, result);
|
||||
} else {
|
||||
// this is due to devices which have a buggy implememtation (and show a broken string also
|
||||
// in ETS tool)
|
||||
logger.debug("Ignoring FRIENDLY_NAME of device {} as it contains non-printable characters",
|
||||
address);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
// allowed to fail, optional
|
||||
}
|
||||
|
||||
ret.put(MANUFACTURER_NAME, manufacturerID);
|
||||
if (serialNo != null) {
|
||||
|
@ -119,16 +267,15 @@ public class DeviceInspector {
|
|||
if (hardwareType != null) {
|
||||
ret.put(MANUFACTURER_HARDWARE_TYPE, hardwareType);
|
||||
}
|
||||
if (firmwareRevision != null) {
|
||||
ret.put(MANUFACTURER_FIRMWARE_REVISION, firmwareRevision);
|
||||
logger.debug("Identified device {} as a {}, type {}, revision {}, serial number {}", address,
|
||||
manufacturerID, hardwareType, firmwareRevision, serialNo);
|
||||
}
|
||||
ret.put(MAX_APDU_LENGTH, maxApdu);
|
||||
logger.debug("Identified device {} as {}, type {}, revision {}, serial number {}, max APDU {}", address,
|
||||
manufacturerID, hardwareType, firmwareRevision, serialNo, maxApdu);
|
||||
} else {
|
||||
logger.debug("The KNX device with address {} does not expose a Device Object", address);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("Interrupted while fetching the device description for a device '{}' : {}", address,
|
||||
e.getMessage());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -136,20 +283,45 @@ public class DeviceInspector {
|
|||
return input == null ? null : DataUnitBuilder.toHex(input, separator);
|
||||
}
|
||||
|
||||
private Map<String, String> readDeviceDescription(IndividualAddress address) {
|
||||
/**
|
||||
* @implNote {@link readDeviceDescription(address)} tries to read device description from the KNX device.
|
||||
* According to KNX specification, eihter device descriptor DD0 or DD2 must be implemented.
|
||||
* Currently only data from DD0 is returned; DD2 is just logged in debug mode.
|
||||
*
|
||||
* @param address Individual address of KNX device
|
||||
* @return List of device properties
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private Map<String, String> readDeviceDescription(IndividualAddress address) throws InterruptedException {
|
||||
Map<String, String> ret = new HashMap<>();
|
||||
byte[] data = getClient().readDeviceDescription(address, 0, false, OPERATION_TIMEOUT);
|
||||
if (data != null) {
|
||||
try {
|
||||
final DD0 dd = DeviceDescriptor.DD0.from(data);
|
||||
|
||||
ret.put(FIRMWARE_TYPE, Firmware.getName(dd.firmwareType()));
|
||||
ret.put(FIRMWARE_VERSION, Firmware.getName(dd.firmwareVersion()));
|
||||
ret.put(FIRMWARE_SUBVERSION, Firmware.getName(dd.firmwareSubcode()));
|
||||
logger.debug("The device with address {} is of type {}, version {}, subversion {}", address,
|
||||
Firmware.getName(dd.firmwareType()), Firmware.getName(dd.firmwareVersion()),
|
||||
Firmware.getName(dd.firmwareSubcode()));
|
||||
ret.put(DEVICE_MASK_VERSION, String.format("%04X", dd.maskVersion()));
|
||||
ret.put(DEVICE_PROFILE, dd.deviceProfile());
|
||||
ret.put(DEVICE_MEDIUM_TYPE, getMediumType(dd.mediumType()));
|
||||
logger.debug("The device with address {} has mask {} ({}, medium {})", address,
|
||||
ret.get(DEVICE_MASK_VERSION), ret.get(DEVICE_PROFILE), ret.get(DEVICE_MEDIUM_TYPE));
|
||||
} catch (KNXIllegalArgumentException e) {
|
||||
logger.warn("Can not parse Device Descriptor 0 of device with address {}: {}", address, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
logger.debug("The KNX device with address {} does not expose a Device Descriptor", address);
|
||||
logger.debug("The device with address {} does not expose a Device Descriptor type 0", address);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
Thread.sleep(OPERATION_INTERVAL);
|
||||
data = getClient().readDeviceDescription(address, 2, false, OPERATION_TIMEOUT);
|
||||
if (data != null) {
|
||||
try {
|
||||
final DD2 dd = DeviceDescriptor.DD2.from(data);
|
||||
logger.debug("The device with address {} is has DD2 {}", address, dd.toString());
|
||||
} catch (KNXIllegalArgumentException e) {
|
||||
logger.warn("Can not parse device descriptor 2 of device with address {}: {}", address,
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -169,4 +341,23 @@ public class DeviceInspector {
|
|||
value = value << 16 | data[2] & 0xff << 8 | data[3] & 0xff;
|
||||
return value;
|
||||
}
|
||||
|
||||
private static String getMediumType(int type) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
return "TP";
|
||||
case 1:
|
||||
return "PL";
|
||||
case 2:
|
||||
return "RF";
|
||||
case 3:
|
||||
return "TP0 (deprecated)";
|
||||
case 4:
|
||||
return "PL123 (deprecated)";
|
||||
case 5:
|
||||
return "IP";
|
||||
default:
|
||||
return "unknown (" + type + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,9 +41,13 @@ public class DeviceConstants {
|
|||
public static final int ASSOCIATION_TABLE_OBJECT = 2; // Associationtable Object
|
||||
public static final int APPLICATION_PROGRAM_TABLE = 3; // Application Program Object
|
||||
public static final int INTERFACE_PROGRAM_OBJECT = 4; // Interface Program Object
|
||||
public static final int ROUTER_OBJECT = 6; // Router Object
|
||||
public static final int GROUPOBJECT_OBJECT = 9; // Group Object Object
|
||||
public static final int KNXNET_IP_OBJECT = 11; // KNXnet/IP Parameter Object
|
||||
|
||||
// Property IDs for device information;
|
||||
public static final int HARDWARE_TYPE = 78;
|
||||
public static final int HARDWARE_TYPE = 78; // to be used with DEVICE_OBJECT
|
||||
public static final int MAX_ROUTED_APDU_LENGTH = 58; // to be used with ADDRESS_TABLE_OBJECT, renamed due to name
|
||||
// conflict in standard (PID.MAX_APDULENGTH used with
|
||||
// DEVICE_OBJECT)
|
||||
}
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2010-2023 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.knx.internal.handler;
|
||||
|
||||
/**
|
||||
* Enumeration containing the firmware types.
|
||||
*
|
||||
* @author Karel Goderis - Initial contribution
|
||||
*/
|
||||
public enum Firmware {
|
||||
F0(0, "BCU 1, BCU 2, BIM M113"),
|
||||
F1(1, "Unidirectional devices"),
|
||||
F3(3, "Property based device management"),
|
||||
F7(7, "BIM M112"),
|
||||
F8(8, "IR Decoder, TP1 legacy"),
|
||||
F9(9, "Repeater, Coupler");
|
||||
|
||||
private int code;
|
||||
private String name;
|
||||
|
||||
private Firmware(int code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String getName(int code) {
|
||||
for (Firmware c : Firmware.values()) {
|
||||
if (c.code == code) {
|
||||
return c.name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ public enum Manufacturer {
|
|||
M30(30, "Feller"),
|
||||
M32(32, "DEHN & SÖHNE"),
|
||||
M33(33, "CRABTREE"),
|
||||
M34(34, "eVoKNX"),
|
||||
M36(36, "Paul Hochköpper"),
|
||||
M37(37, "Altenburger Electronic"),
|
||||
M41(41, "Grässlin"),
|
||||
|
@ -321,7 +322,8 @@ public enum Manufacturer {
|
|||
M356(356, "AYPRO Technology"),
|
||||
M357(357, "Hefei Ecolite Software"),
|
||||
M358(358, "Enno"),
|
||||
M359(359, "Ohosure");
|
||||
M359(359, "Ohosure"),
|
||||
M373(373, "ZF Friedrichshafen AG");
|
||||
|
||||
private int code;
|
||||
private String name;
|
||||
|
@ -342,6 +344,6 @@ public enum Manufacturer {
|
|||
return c.name;
|
||||
}
|
||||
}
|
||||
return "Unknown";
|
||||
return "Unknown (" + code + ")";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue