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

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

There is a newer version: 2.6-rc1
Show newest version
/*
    Calimero 2 - A library for KNX network access
    Copyright (c) 2015, 2018 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.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.TreeSet;
import java.util.stream.Collectors;

import tuwien.auto.calimero.IndividualAddress;
import tuwien.auto.calimero.KNXException;
import tuwien.auto.calimero.KNXFormatException;
import tuwien.auto.calimero.KNXIllegalArgumentException;
import tuwien.auto.calimero.Settings;
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.KNXNetworkLinkUsb;
import tuwien.auto.calimero.link.medium.KNXMediumSettings;
import tuwien.auto.calimero.link.medium.TPSettings;
import tuwien.auto.calimero.mgmt.ManagementProcedures;
import tuwien.auto.calimero.mgmt.ManagementProceduresImpl;

/**
 * ProgMode lists the current KNX devices in programming mode, and allows to set the programming mode of a device. The
 * tool supports network access using KNXnet/IP, KNX IP, USB, FT1.2, and TP-UART.
 * 

* Run the tool by using either {@link ProgMode#main(String[])} or {@link Runnable#run()}. */ public class ProgMode implements Runnable { private static final String tool = "ProgMode"; private static final String sep = System.getProperty("line.separator"); /** Contains tool options after parsing command line. */ private final Map options = new HashMap<>(); /** * Creates a new ProgMode object using the supplied arguments. * * @param args options for the tool, see {@link #main(String[])} * @throws KNXIllegalArgumentException on missing or wrong formatted option value */ public ProgMode(final String[] args) { try { parseOptions(args); } catch (final KNXIllegalArgumentException e) { throw e; } catch (KNXFormatException | RuntimeException e) { throw new KNXIllegalArgumentException(e.getMessage(), e); } } /** * Entry point for running the ProgMode tool from the command line. *

* 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, use 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
  • *
  • --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
  • *
  • --ft12 -f use FT1.2 serial communication
  • *
  • --usb -u use KNX USB communication
  • *
  • --tpuart use TP-UART communication
  • *
  • --medium -m id  KNX medium [tp1|p110|rf|knxip] (defaults to tp1)
  • *
  • --domain address  domain address on open KNX medium (PL or RF)
  • *
  • --knx-address -k KNX address  KNX device address of local endpoint
  • *
* 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. *

* Supported commands: *

    *
  • on device   switch programming mode on
  • *
  • off device   switch programming mode off
  • *
* * @param args command line arguments for the tool */ public static void main(final String[] args) { try { new ProgMode(args).run(); } catch (final Throwable t) { out("error parsing arguments (use --help): " + t); } } @Override public void run() { if (options.containsKey("about")) { ((Runnable) options.get("about")).run(); return; } Exception thrown = null; boolean canceled = false; try (KNXNetworkLink link = createLink(); ManagementProcedures mgmt = new ManagementProceduresImpl(link)) { final String cmd = (String) options.get("command"); if ("status".equals(cmd)) { System.out.print("Device(s) in programming mode ..."); System.out.flush(); while (true) devicesInProgMode(mgmt.readAddress()); } else mgmt.setProgrammingMode((IndividualAddress) options.get("device"), "on".equals(cmd)); } catch (KNXException | RuntimeException e) { thrown = e; } catch (final InterruptedException e) { canceled = true; Thread.currentThread().interrupt(); } finally { onCompletion(thrown, canceled); } } protected void devicesInProgMode(final IndividualAddress... devices) { final String output = devices.length == 0 ? "none" : new TreeSet<>(Arrays.asList(devices)).stream().map(Objects::toString).collect(Collectors.joining(", ")); System.out.print("\33[2K\rDevice(s) in programming mode: " + output); System.out.flush(); } /** * 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(tool + " got canceled"); if (thrown != null) out(tool + " error", thrown); } private KNXNetworkLink createLink() throws KNXException, InterruptedException { final String host = (String) options.get("host"); final KNXMediumSettings medium = (KNXMediumSettings) options.get("medium"); if (options.containsKey("ft12")) { // create FT1.2 network link try { return new KNXNetworkLinkFT12(Integer.parseInt(host), medium); } catch (final NumberFormatException e) { return new KNXNetworkLinkFT12(host, medium); } } if (options.containsKey("usb")) { // create KNX USB HID network link return new KNXNetworkLinkUsb(host, medium); } if (options.containsKey("tpuart")) { // create TP-UART link final IndividualAddress device = (IndividualAddress) options.get("knx-address"); medium.setDeviceAddress(device); return new KNXNetworkLinkTpuart(host, medium, Collections.emptyList()); } // create IP link final InetSocketAddress local = Main.createLocalSocket((InetAddress) options.get("localhost"), (Integer) options.get("localport")); final InetAddress addr = Main.parseHost(host); if (addr.isMulticastAddress()) return KNXNetworkLinkIP.newRoutingLink(local.getAddress(), addr, medium); final InetSocketAddress remote = new InetSocketAddress(addr, (Integer) options.get("port")); return KNXNetworkLinkIP.newTunnelingLink(local, remote, options.containsKey("nat"), medium); } private void parseOptions(final String[] args) throws KNXFormatException { if (args.length == 0) { options.put("about", (Runnable) ProgMode::showToolInfo); return; } // add defaults options.put("port", 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)); options.put("command", "status"); boolean setmode = false; int i = 0; for (; i < args.length; i++) { final String arg = args[i]; if (Main.isOption(arg, "help", "h")) { options.put("about", (Runnable) ProgMode::showUsage); return; } if (Main.isOption(arg, "version", null)) { options.put("about", (Runnable) ProgMode::showVersion); return; } else if (Main.isOption(arg, "verbose", "v")) options.put("verbose", null); else if (Main.isOption(arg, "localhost", null)) options.put("localhost", Main.parseHost(args[++i])); else if (Main.isOption(arg, "localport", null)) options.put("localport", Integer.decode(args[++i])); else if (Main.isOption(arg, "port", "p")) options.put("port", Integer.decode(args[++i])); else if (Main.isOption(arg, "nat", "n")) options.put("nat", null); else if (Main.isOption(arg, "ft12", "f")) options.put("ft12", null); else if (Main.isOption(arg, "usb", "u")) options.put("usb", null); else if (Main.isOption(arg, "tpuart", null)) options.put("tpuart", null); else if (Main.isOption(arg, "medium", "m")) options.put("medium", Main.getMedium(args[++i])); else if (Main.isOption(arg, "domain", null)) options.put("domain", Long.decode(args[++i])); else if (Main.isOption(arg, "knx-address", "k")) options.put("knx-address", Main.getAddress(args[++i])); else if (arg.equals("on") || arg.equals("off")) { options.put("command", arg); setmode = true; } else if (setmode) options.put("device", new IndividualAddress(arg)); else if (!options.containsKey("host")) options.put("host", arg); else options.put("device", new IndividualAddress(arg)); } if (!options.containsKey("host")) throw new KNXIllegalArgumentException("no communication device/host specified"); if (options.containsKey("ft12") && !options.containsKey("remote")) throw new KNXIllegalArgumentException("--remote option is mandatory with --ft12"); if (setmode != options.containsKey("device")) throw new KNXIllegalArgumentException("setting programming mode requires mode and KNX device address"); Main.setDomainAddress(options); } private static void showToolInfo() { out(tool + " - Check/set device(s) in programming mode"); showVersion(); out("Use --help for help message"); } private static void showUsage() { final StringBuilder sb = new StringBuilder(); sb.append("Usage: ").append(tool).append(" [options] [on|off ]").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(" --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(" --ft12 -f use FT1.2 serial communication").append(sep); sb.append(" --usb -u use KNX USB communication").append(sep); sb.append(" --tpuart use TP-UART communication").append(sep); sb.append(" --medium -m KNX medium [tp1|p110|rf|knxip] (default tp1)").append(sep); sb.append(" --domain
domain address on KNX PL/RF medium (defaults to broadcast domain)") .append(sep); sb.append("Commands:").append(sep); sb.append(" on switch programming mode on").append(sep); sb.append(" off switch programming mode off").append(sep); out(sb); } private static void showVersion() { out(Settings.getLibraryHeader(false)); } private static void out(final CharSequence s, final Throwable... t) { if (t.length > 0 && t[0] != null) { System.out.print(s + ": "); t[0].printStackTrace(); } else System.out.println(s); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy