All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tuwien.auto.calimero.tools.Property Maven / Gradle / Ivy

There is a newer version: 2.6-rc1
Show newest version
/*
    Calimero 2 - A library for KNX network access
    Copyright (c) 2010, 2016 B. Malinowsky

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Linking this library statically or dynamically with other modules is
    making a combined work based on this library. Thus, the terms and
    conditions of the GNU General Public License cover the whole
    combination.

    As a special exception, the copyright holders of this library give you
    permission to link this library with independent modules to produce an
    executable, regardless of the license terms of these independent
    modules, and to copy and distribute the resulting executable under terms
    of your choice, provided that you also meet, for each linked independent
    module, the terms and conditions of the license of that module. An
    independent module is a module which is not derived from or based on
    this library. If you modify this library, you may extend this exception
    to your version of the library, but you are not obligated to do so. If
    you do not wish to do so, delete this exception statement from your
    version.
*/

package tuwien.auto.calimero.tools;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import tuwien.auto.calimero.CloseEvent;
import tuwien.auto.calimero.DataUnitBuilder;
import tuwien.auto.calimero.IndividualAddress;
import tuwien.auto.calimero.Settings;
import tuwien.auto.calimero.exception.KNXException;
import tuwien.auto.calimero.exception.KNXFormatException;
import tuwien.auto.calimero.exception.KNXIllegalArgumentException;
import tuwien.auto.calimero.knxnetip.KNXnetIPConnection;
import tuwien.auto.calimero.link.KNXNetworkLink;
import tuwien.auto.calimero.link.KNXNetworkLinkFT12;
import tuwien.auto.calimero.link.KNXNetworkLinkIP;
import tuwien.auto.calimero.link.KNXNetworkLinkTpuart;
import tuwien.auto.calimero.link.medium.KNXMediumSettings;
import tuwien.auto.calimero.link.medium.PLSettings;
import tuwien.auto.calimero.link.medium.RFSettings;
import tuwien.auto.calimero.link.medium.TPSettings;
import tuwien.auto.calimero.log.LogLevel;
import tuwien.auto.calimero.log.LogManager;
import tuwien.auto.calimero.log.LogService;
import tuwien.auto.calimero.log.LogStreamWriter;
import tuwien.auto.calimero.log.LogWriter;
import tuwien.auto.calimero.mgmt.Description;
import tuwien.auto.calimero.mgmt.LocalDeviceMgmtAdapter;
import tuwien.auto.calimero.mgmt.PropertyAdapter;
import tuwien.auto.calimero.mgmt.PropertyAdapterListener;
import tuwien.auto.calimero.mgmt.PropertyClient;
import tuwien.auto.calimero.mgmt.PropertyClient.PropertyKey;
import tuwien.auto.calimero.mgmt.RemotePropertyServiceAdapter;

/**
 * A tool for Calimero showing features of the {@link PropertyClient} used for KNX
 * property access.
 * 

* Property is a {@link Runnable} tool implementation to set or get a KNX property from an Interface * Object Server (IOS), get its KNX property description, or scan the KNX descriptions available. It * supports network access using a KNXnet/IP, KNX IP, FT1.2, or TP-UART connection.
* The tool implementation mainly interacts with {@link PropertyClient}, which offers high-level * access to KNX property information. It also shows creation of the {@link PropertyAdapter}, * necessary for a property client to work. All queried property values, as well as occurring * problems are written to System.out. *

* When starting this tool from the console, the main-method of this class is invoked, * otherwise use it in the context appropriate to {@link Runnable}. Take a look at the command line * options to configure the tool with the appropriate communication settings. * * @author B. Malinowsky */ public class Property implements Runnable, PropertyAdapterListener { private static final String tool = "Property"; private static final String sep = System.getProperty("line.separator"); static LogService out = LogManager.getManager().getLogService("tools"); /** Contains tool options after parsing command line. */ protected final Map options = new HashMap(); protected PropertyClient pc; private KNXNetworkLink lnk; private Map definitions; private final Thread interruptOnClose; /** * Constructs a new Property object. *

* * @param args options for the property tool, see {@link #main(String[])} * @throws KNXIllegalArgumentException on missing or wrong formatted option value */ public Property(final String[] args) { interruptOnClose = Thread.currentThread(); try { parseOptions(args); } catch (final KNXIllegalArgumentException e) { throw e; } catch (final RuntimeException e) { throw new KNXIllegalArgumentException(e.getMessage(), e); } } /** * Entry point for running the Property tool from the console. *

* A communication device, host, or port identifier has to be supplied to specify the endpoint * for KNX network access.
* To show the usage message of this tool on the console, supply the command line option -help * (or -h).
* Command line options are treated case sensitive. Available options are: *

    *
  • -help -h show help message
  • *
  • -version show tool/library version and exit
  • *
  • -verbose -v enable verbose status output
  • *
  • -local -l local device management (default)
  • *
  • -remote -r KNX addr  remote property service
  • *
  • -definitions -d file  use property definition file
  • *
  • -localhost id  local IP/host name
  • *
  • -localport number  local UDP port (default system assigned)
  • *
  • -port -p number  UDP port on host (default 3671)
  • *
  • -nat -n enable Network Address Translation
  • *
  • -serial -s use FT1.2 serial communication
  • *
  • -tpuart use TP-UART communication
  • *
* For local device management these options are available: *
    *
  • -emulatewriteenable -e check write-enable of a property
  • *
* For remote property service these options are available: *
    *
  • -routing use KNXnet/IP routing
  • *
  • -medium -m id  KNX medium [tp1|p110|rf] (defaults to tp1) *
  • *
  • -knx-address -k KNX address  KNX device address of local * endpoint
  • *
  • -connect -c connection oriented mode
  • *
  • -authorize -a key  authorize key to access the KNX device
  • *
* Use one of the following commands for property access, with object-idx being the * interface object index, and pid the KNX property identifier: *
    *
  • get object-idx pid [start-idx elements] get the property value(s) *
  • *
  • set object-idx pid [start-idx] string-value set the property * string-formatted value
  • *
  • set object-idx pid start-idx elements [\"0x\"|\"0\"|\"b\"]data set * the property data
  • *
  • desc object-idx pid get the property description of the property ID *
  • *
  • desc object-idx "i" prop-idx get the property description of the * property index
  • *
  • scan [object-idx] list interface object type descriptions (of the * indexed interface object)
  • *
  • scan [object-idx] "all" list all property descriptions (of the * indexed interface object)
  • *
  • ? show command help
  • *
* The -knx-address option is only necessary if an access protocol is selected * that directly communicates with the KNX network, i.e., KNX IP or TP-UART. The selected KNX * individual address shall be unique in a network, and the subnetwork address (area and line) * should be set to match the network configuration. * * @param args command line options for the property tool */ public static void main(final String[] args) { final LogWriter w = LogStreamWriter.newUnformatted(LogLevel.WARN, System.out, true, false); LogManager.getManager().addWriter(null, w); try { final Property p = new Property(args); if (p.options.containsKey("verbose")) w.setLogLevel(LogLevel.INFO); p.run(); } catch (final Throwable t) { out.log(LogLevel.ERROR, "parsing option", t); } finally { LogManager.getManager().shutdown(true); } } /* (non-Javadoc) * @see java.lang.Runnable#run() */ public void run() { // ??? as with the other tools, maybe put this into the try block to also call onCompletion if (options.isEmpty()) { out.log(LogLevel.ALWAYS, tool + " - Access KNX properties", null); showVersion(); out.log(LogLevel.ALWAYS, "Type -help for help message", null); return; } if (options.containsKey("help")) { showUsage(); return; } if (options.containsKey("version")) { showVersion(); return; } // load property definitions from resource, if any Collection defs = null; if (options.containsKey("definitions")) { try { defs = PropertyClient.loadDefinitions((String) options.get("definitions"), null); } catch (final KNXException e) { out.log(LogLevel.ERROR, "loading definitions from " + options.get("definitions") + " failed", e); } } Exception thrown = null; boolean canceled = true; try { // create a property adapter and supply it to a new property client pc = new PropertyClient(createAdapter()); // check if user supplied a XML resource with property definitions if (defs != null) { pc.addDefinitions(defs); definitions = pc.getDefinitions(); } // run the user command runCommand((String[]) options.get("command")); } catch (final KNXException e) { thrown = e; } catch (final RuntimeException e) { thrown = e; } catch (final InterruptedException e) { canceled = true; Thread.currentThread().interrupt(); } finally { if (pc != null) pc.close(); if (lnk != null) lnk.close(); onCompletion(thrown, canceled); } } /* (non-Javadoc) * @see tuwien.auto.calimero.mgmt.PropertyAdapterListener#adapterClosed( * tuwien.auto.calimero.CloseEvent) */ public void adapterClosed(final CloseEvent e) { out.log(LogLevel.INFO, "connection closed (" + e.getReason() + ")", null); if (e.getInitiator() != CloseEvent.USER_REQUEST) interruptOnClose.interrupt(); } /** * Runs a single command. * * @param cmd the command to execute together with its parameters */ protected void runCommand(final String[] cmd) { if (cmd == null) return; try { final String what = cmd[0]; if ("get".equals(what)) getProperty(cmd); else if ("set".equals(what)) setProperty(cmd); else if ("scan".equals(what)) scanProperties(cmd); else if ("desc".equals(what)) getDescription(cmd); else if ("?".equals(what)) showCommandList(); else out.log(LogLevel.INFO, "unknown command, type ? for help", null); } catch (final KNXException e) { out.log(LogLevel.ERROR, e.getMessage(), null); } catch (final NumberFormatException e) { out.log(LogLevel.ERROR, "invalid number (" + e.getMessage() + ")", null); } } /** * Called by this tool on completion. *

* * @param thrown the thrown exception if operation completed due to a raised exception, * null otherwise * @param canceled whether the operation got canceled before its planned end */ protected void onCompletion(final Exception thrown, final boolean canceled) { if (canceled) out.log(LogLevel.INFO, "reading property canceled", null); if (thrown != null) out.log(LogLevel.ERROR, "on completion", thrown); } /** * Creates the property adapter to be used with the property client depending on the supplied * user options. *

* There are two types of property adapters. One is for local device management to access KNX * properties of the connected interface, specifically, KNXnet/IP. The other * type uses remote property services to access KNX properties of a KNX device over the KNX bus. * If a remote property service adapter is requested, the required KNX network link to access * the KNX network is automatically created. * * @return the created adapter * @throws KNXException on adapter creation problem * @throws InterruptedException on interrupted thread */ private PropertyAdapter createAdapter() throws KNXException, InterruptedException { final String host = (String) options.get("host"); // decide what type of adapter to create if (options.containsKey("local")) return createLocalDMAdapter(host); return createRemoteAdapter(host); } /** * Creates a KNXnet/IP local device management adapter. * * @param host remote host * @return local device management adapter * @throws KNXException on adapter creation problem * @throws InterruptedException on interrupted thread */ private PropertyAdapter createLocalDMAdapter(final String host) throws KNXException, InterruptedException { final InetSocketAddress local = createLocalSocket((InetAddress) options.get("localhost"), (Integer) options.get("localport")); return new LocalDeviceMgmtAdapter(local, new InetSocketAddress(host, ((Integer) options.get("port")).intValue()), options.containsKey("nat"), this, options.containsKey("emulatewriteenable")); } /** * Creates the KNX network link and remote property service adapter for one device in the KNX network. * * @param host remote host * @return remote property service adapter * @throws KNXException on adapter creation problem * @throws InterruptedException on interrupted thread */ private PropertyAdapter createRemoteAdapter(final String host) throws KNXException, InterruptedException { final KNXMediumSettings medium = (KNXMediumSettings) options.get("medium"); if (options.containsKey("serial")) { // create FT1.2 network link try { lnk = new KNXNetworkLinkFT12(Integer.parseInt(host), medium); } catch (final NumberFormatException e) { lnk = new KNXNetworkLinkFT12(host, medium); } } else if (options.containsKey("tpuart")) { // create TP-UART link final IndividualAddress device = (IndividualAddress) options.get("knx-address"); medium.setDeviceAddress(device); lnk = new KNXNetworkLinkTpuart(host, medium, Collections.emptyList()); } else { final InetSocketAddress local = createLocalSocket( (InetAddress) options.get("localhost"), (Integer) options.get("localport")); final InetSocketAddress sa = new InetSocketAddress(host, ((Integer) options.get("port")).intValue()); lnk = new KNXNetworkLinkIP(options.containsKey("routing") ? KNXNetworkLinkIP.ROUTING : KNXNetworkLinkIP.TUNNELING, local, sa, options.containsKey("nat"), medium); } final IndividualAddress remote = (IndividualAddress) options.get("remote"); // if an authorization key was supplied, the adapter uses // connection oriented mode and tries to authenticate final byte[] authKey = (byte[]) options.get("authorize"); if (authKey != null) return new RemotePropertyServiceAdapter(lnk, remote, this, authKey); return new RemotePropertyServiceAdapter(lnk, remote, this, options.containsKey("connect")); } private void printDescription(final Description d) { final StringBuffer buf = new StringBuffer(); buf.append(alignRight(d.getPropIndex())); buf.append(" OT ").append(alignRight(d.getObjectType())); buf.append(", OI ").append(d.getObjectIndex()); buf.append(", PID ").append(alignRight(d.getPID())); tuwien.auto.calimero.mgmt.PropertyClient.Property p = getPropertyDef(d.getObjectType(), d.getPID()); if (p == null) p = getPropertyDef(PropertyKey.GLOBAL_OBJTYPE, d.getPID()); if (p != null) { buf.append(" "); buf.append(p.getName()); while (buf.length() < 55) buf.append(' '); buf.append(" ("); buf.append(p.getPIDName()); buf.append(")"); } final String pdtDef = p != null ? Integer.toString(p.getPDT()) : "-"; buf.append(", PDT " + (d.getPDT() == -1 ? pdtDef : Integer.toString(d.getPDT()))); buf.append(", curr. elems " + d.getCurrentElements()); buf.append(", max. " + d.getMaxElements()); buf.append(", r/w access " + d.getReadLevel() + "/" + d.getWriteLevel()); buf.append(d.isWriteEnabled() ? ", w.enabled" : ", r.only"); System.out.println(buf.toString()); } private static String alignRight(final int value) { return value < 10 ? " " + value : "" + value; } private tuwien.auto.calimero.mgmt.PropertyClient.Property getPropertyDef(final int objType, final int pid) { if (definitions == null) return null; return (tuwien.auto.calimero.mgmt.PropertyClient.Property) definitions .get(new PropertyClient.PropertyKey(objType, pid)); } private void parseOptions(final String[] args) { if (args.length == 0) return; // add defaults options.put("port", new Integer(KNXnetIPConnection.DEFAULT_PORT)); options.put("medium", TPSettings.TP1); // default subnetwork address for TP1 and unregistered device options.put("knx-address", new IndividualAddress(0, 0x02, 0xff)); int i = 0; for (; i < args.length; i++) { final String arg = args[i]; if (isOption(arg, "-help", "-h")) { options.put("help", null); return; } if (isOption(arg, "-version", null)) { options.put("version", null); return; } if (isOption(arg, "-local", "-l")) options.put("local", null); else if (isOption(arg, "-remote", "-r")) try { options.put("remote", new IndividualAddress(args[++i])); } catch (final KNXFormatException e) { throw new KNXIllegalArgumentException(e.getMessage(), e); } else if (isOption(arg, "-definitions", "-d")) options.put("definitions", args[++i]); else if (isOption(arg, "-verbose", "-v")) options.put("verbose", null); else if (isOption(arg, "-localhost", null)) parseHost(args[++i], true, options); else if (isOption(arg, "-localport", null)) options.put("localport", Integer.decode(args[++i])); else if (isOption(arg, "-port", "-p")) options.put("port", Integer.decode(args[++i])); else if (isOption(arg, "-nat", "-n")) options.put("nat", null); else if (isOption(arg, "-serial", "-s")) options.put("serial", null); else if (isOption(arg, "-tpuart", null)) options.put("tpuart", null); else if (isOption(arg, "-medium", "-m")) options.put("medium", getMedium(args[++i])); else if (isOption(arg, "-emulatewriteenable", "-e")) options.put("emulatewriteenable", null); else if (isOption(arg, "-connect", "-c")) options.put("connect", null); else if (isOption(arg, "-authorize", "-a")) options.put("authorize", getAuthorizeKey(args[++i])); else if (isOption(arg, "-routing", null)) options.put("routing", null); else if (arg.equals("get") || arg.equals("set") || arg.equals("desc") || arg.equals("scan")) { final List cmd = new ArrayList(); cmd.add(arg); while (addOptionIfInteger(cmd, args, i + 1)) ++i; if (arg.equals("desc") && i + 1 < args.length && args[i + 1].equals("i")) { cmd.add(args[++i]); cmd.add(args[++i]); } if (arg.equals("scan") && i + 1 < args.length && args[i + 1].equals("all")) cmd.add(args[++i]); options.put("command", cmd.toArray(new String[0])); } else if (arg.equals("?")) options.put("command", new String[] { "?" }); else if (!options.containsKey("host")) options.put("host", arg); else throw new KNXIllegalArgumentException("unknown option " + arg); } if (!options.containsKey("remote")) options.put("local", null); if (!options.containsKey("host")) throw new KNXIllegalArgumentException("no communication device/host specified"); if (options.containsKey("serial") && !options.containsKey("remote")) throw new KNXIllegalArgumentException("-remote option is mandatory with -serial"); } // // utility methods // private static boolean addOptionIfInteger(final List cmd, final String[] args, final int index) { if (index < args.length) try { final String arg = args[index]; Integer.decode(arg); return cmd.add(arg); } catch (final NumberFormatException expected) {} return false; } private void showVersion() { out.log(LogLevel.ALWAYS, Settings.getLibraryHeader(false), null); } private void getProperty(final String[] args) throws KNXException { String s = "sorry, wrong number of arguments"; if (args.length == 2 && args[1].equals("?")) s = "get object-idx pid [start-idx elements]"; else if (args.length == 3 || args.length == 5) { final int oi = toInt(args[1]); final int pid = toInt(args[2]); try { if (args.length == 3) s = pc.getProperty(oi, pid); else s = Arrays.asList(pc.getPropertyTranslated(oi, pid, toInt(args[3]), toInt(args[4])).getAllValues()).toString(); } catch (final KNXException e) { if (args.length == 3) s = "0x" + DataUnitBuilder.toHex(pc.getProperty(oi, pid, 1, 1), ""); else { final int elems = toInt(args[4]); final String hex = DataUnitBuilder.toHex( pc.getProperty(oi, pid, toInt(args[3]), elems), ""); final int chars = hex.length() / elems; for (int i = 0; i < elems; ++i) s += "0x" + hex.substring(i * chars, (i + 1) * chars) + " "; } } } out.log(LogLevel.ALWAYS, s, null); } private void getDescription(final String[] args) throws KNXException { if (args.length == 3) printDescription(pc.getDescription(toInt(args[1]), toInt(args[2]))); else if (args.length == 4 && args[2].equals("i")) printDescription(pc.getDescriptionByIndex(toInt(args[1]), toInt(args[3]))); else if (args.length == 2 && args[1].equals("?")) printHelp("desc object-idx pid" + sep + "desc object-idx \"i\" prop-idx"); else out.log(LogLevel.INFO, "sorry, wrong number of arguments", null); } private void setProperty(final String[] args) throws KNXException { if (args.length < 4 || args.length > 6) { out.log(LogLevel.INFO, "sorry, wrong number of arguments", null); return; } if (args.length == 2 && args[1].equals("?")) printHelp("set object-idx pid [start-idx] string-value" + sep + "set object-idx pid start-idx elements [\"0x\"|\"0\"|\"b\"]data" + sep + "(use hexadecimal format for more than 8 byte data or leading zeros)"); final int cnt = args.length; final int oi = toInt(args[1]); final int pid = toInt(args[2]); if (cnt == 4) pc.setProperty(oi, pid, 1, args[3]); else if (cnt == 5) pc.setProperty(oi, pid, toInt(args[3]), args[4]); else if (cnt == 6) pc.setProperty(oi, pid, toInt(args[3]), toInt(args[4]), toByteArray(args[5])); } private void scanProperties(final String[] args) throws KNXException { final int cnt = args.length; List l = Collections.EMPTY_LIST; if (cnt == 1) l = pc.scanProperties(false); else if (cnt == 2) { if (args[1].equals("all")) l = pc.scanProperties(true); else if (args[1].equals("?")) printHelp("scan [object-idx] [\"all\" for all object properties]"); else l = pc.scanProperties(toInt(args[1]), false); } else if (cnt == 3 && args[2].equals("all")) l = pc.scanProperties(toInt(args[1]), true); else out.log(LogLevel.INFO, "sorry, wrong number of arguments", null); for (final Iterator i = l.iterator(); i.hasNext();) { final Description d = (Description) i.next(); printDescription(d); } } private void showCommandList() { final StringBuffer buf = new StringBuffer(); buf.append("commands: get | set | desc | scan (append ? for help)" + sep); buf.append("get - read property value(s)" + sep); buf.append("set - write property value(s)" + sep); buf.append("desc - read one property description" + sep); buf.append("scan - read property descriptions" + sep); out.log(LogLevel.INFO, buf.toString(), null); } private void printHelp(final String help) { out.log(LogLevel.INFO, help, null); } private static void showUsage() { final StringBuffer sb = new StringBuffer(); sb.append("Usage: ").append(tool).append(" [options] ").append(sep); sb.append("Options:").append(sep); sb.append(" -help -h show this help message").append(sep); sb.append(" -version show tool/library version and exit").append(sep); sb.append(" -verbose -v enable verbose status output").append(sep); sb.append(" -local -l local device management").append(sep); sb.append(" -remote -r remote property service").append(sep); sb.append(" -definitions -d use property definition file").append(sep); sb.append(" -localhost local IP/host name").append(sep); sb.append(" -localport local UDP port (default system assigned)").append(sep); sb.append(" -port -p UDP port on (default ") .append(KNXnetIPConnection.DEFAULT_PORT).append(")").append(sep); sb.append(" -nat -n enable Network Address Translation").append(sep); sb.append(" -serial -s use FT1.2 serial communication").append(sep); sb.append(" -tpuart use TP-UART communication").append(sep); sb.append("Options for local device management mode only:").append(sep); sb.append(" -emulatewriteenable -e check write-enable of a property").append(sep); sb.append("Options for remote property service mode only:").append(sep); sb.append(" -routing use KNXnet/IP routing").append(sep); sb.append(" -medium -m KNX medium [tp1|p110|rf] (default tp1)") .append(sep); sb.append(" -connect -c connection oriented mode").append(sep); sb.append(" -authorize -a authorize key to access KNX device").append(sep); sb.append("Available commands:").append(sep); sb.append(" get [ ] get the property value(s)") .append(sep); sb.append(" set [start-idx] " + "set the formatted property value (according to PDT)").append(sep); sb.append(" set [\"0x\"|\"0\"|\"b\"] " + "set the property data").append(sep); sb.append(" desc " + "get the property description of the property ID").append(sep); sb.append(" desc \"i\" " + "get the property description of the property index").append(sep); sb.append(" scan []" + " list interface object type descriptions").append(sep); sb.append(" scan [] \"all\" list all property descriptions") .append(sep); sb.append(" ? show command help").append(sep); out.log(LogLevel.ALWAYS, sb.toString(), null); } // // utility methods // private static KNXMediumSettings getMedium(final String id) { // for now, the local device address is always left 0 in the // created medium setting, since there is no user cmd line option for this // so KNXnet/IP server will supply address if (id.equals("tp1")) return TPSettings.TP1; else if (id.equals("p110")) return new PLSettings(); else if (id.equals("rf")) return new RFSettings(null); else throw new KNXIllegalArgumentException("unknown medium"); } private static byte[] getAuthorizeKey(final String key) { final long value = Long.decode(key).longValue(); if (value < 0 || value > 0xFFFFFFFFL) throw new KNXIllegalArgumentException("invalid authorize key"); return new byte[] { (byte) (value >> 24), (byte) (value >> 16), (byte) (value >> 8), (byte) value }; } private static void parseHost(final String host, final boolean local, final Map options) { try { options.put(local ? "localhost" : "host", InetAddress.getByName(host)); } catch (final UnknownHostException e) { throw new KNXIllegalArgumentException("failed to read host " + host, e); } } private static InetSocketAddress createLocalSocket(final InetAddress host, final Integer port) { final int p = port != null ? port.intValue() : 0; try { return host != null ? new InetSocketAddress(host, p) : p != 0 ? new InetSocketAddress(InetAddress.getLocalHost(), p) : null; } catch (final UnknownHostException e) { throw new KNXIllegalArgumentException("failed to get local host " + e.getMessage(), e); } } private static boolean isOption(final String arg, final String longOpt, final String shortOpt) { return arg.equals(longOpt) || shortOpt != null && arg.equals(shortOpt); } private static int toInt(final String number) { return Integer.decode(number).intValue(); } private static byte[] toByteArray(final String s) { // use of BigXXX equivalent is a bit awkward, for now this is sufficient ... long l = 0; if (s.startsWith("0x") || s.startsWith("0X")) { final byte[] d = new byte[(s.length() - 1) / 2]; int k = (s.length() & 0x01) != 0 ? 3 : 4; for (int i = 2; i < s.length(); i = k, k += 2) d[(i - 1) / 2] = (byte) Integer.parseInt(s.substring(i, k), 16); return d; } else if (s.length() > 1 && s.startsWith("0")) l = Long.parseLong(s, 8); else if (s.startsWith("b")) l = Long.parseLong(s.substring(1), 2); else l = Long.parseLong(s); int i = 0; for (long test = l; test != 0; test /= 0x100) ++i; final byte[] d = new byte[i == 0 ? 1 : i]; for (; i-- > 0; l /= 0x100) d[i] = (byte) (l & 0xff); return d; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy