/* * ============================================================================ * GNU General Public License * ============================================================================ * * Copyright (C) 2006-2011 Serotonin Software Technologies Inc. http://serotoninsoftware.com * @author Matthew Lohbihler * * 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 3 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, see <http://www.gnu.org/licenses/>. * * When signing a commercial license with Serotonin Software Technologies Inc., * the following extension to GPL is made. A special exception to the GPL is * included to allow you to distribute a combined work that includes BAcnet4J * without being obliged to provide the source code for any proprietary components. */ package com.serotonin.bacnet4j.type.primitive; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.Arrays; import com.serotonin.bacnet4j.base.BACnetUtils; import com.serotonin.bacnet4j.npdu.ip.InetAddrCache; import com.serotonin.bacnet4j.npdu.ip.IpNetwork; import org.free.bacnet4j.util.ArrayUtils; import org.free.bacnet4j.util.IpAddressUtils; import org.free.bacnet4j.util.ByteQueue; public class OctetString extends Primitive { private static final long serialVersionUID = -3557657941142811228L; public static final byte TYPE_ID = 6; private final byte[] value; public OctetString(byte[] value) { this.value = value; } public OctetString(String dottedString) { this(dottedString, IpNetwork.DEFAULT_PORT); } public OctetString(String dottedString, int defaultPort) { dottedString = dottedString.trim(); int colon = dottedString.indexOf(":"); if (colon == -1) { byte[] b = BACnetUtils.dottedStringToBytes(dottedString); if (b.length == 4) value = toBytes(b, defaultPort); else value = b; } else { byte[] ip = BACnetUtils.dottedStringToBytes(dottedString.substring(0, colon)); int port = Integer.parseInt(dottedString.substring(colon + 1)); value = toBytes(ip, port); } } /** * Convenience constructor for MS/TP addresses local to this network. * * @param station * the station id */ public OctetString(byte station) { value = new byte[] { station }; } /** * Convenience constructor for IP addresses local to this network. * * @param ipAddress * @param port */ public OctetString(byte[] ipAddress, int port) { value = toBytes(ipAddress, port); } public OctetString(InetSocketAddress addr) { this(addr.getAddress().getAddress(), addr.getPort()); } public byte[] getBytes() { return value; } private static byte[] toBytes(byte[] ipAddress, int port) { if (ipAddress.length != 4) throw new IllegalArgumentException("IP address must have 4 parts, not " + ipAddress.length); byte[] b = new byte[6]; System.arraycopy(ipAddress, 0, b, 0, ipAddress.length); b[ipAddress.length] = (byte) (port >> 8); b[ipAddress.length + 1] = (byte) port; return b; } // // // I/P convenience // public String getMacAddressDottedString() { return BACnetUtils.bytesToDottedString(value); } public InetAddress getInetAddress() { try { return InetAddress.getByAddress(getIpBytes()); } catch (UnknownHostException e) { throw new RuntimeException(e); } } public InetSocketAddress getInetSocketAddress() { return InetAddrCache.get(getInetAddress(), getPort()); } public int getPort() { if (value.length == 6) return ((value[4] & 0xff) << 8) | (value[5] & 0xff); return -1; } public String toIpString() { return IpAddressUtils.toIpString(getIpBytes()); } public String toIpPortString() { return toIpString() + ":" + getPort(); } public byte[] getIpBytes() { if (value.length == 4) return value; byte[] b = new byte[4]; System.arraycopy(value, 0, b, 0, 4); return b; } // // // MS/TP convenience // public byte getMstpAddress() { return value[0]; } // // Reading and writing // public OctetString(ByteQueue queue) { int length = (int) readTag(queue); value = new byte[length]; queue.pop(value); } @Override public void writeImpl(ByteQueue queue) { queue.push(value); } @Override public long getLength() { return value.length; } @Override protected byte getTypeId() { return TYPE_ID; } @Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + Arrays.hashCode(value); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final OctetString other = (OctetString) obj; if (!Arrays.equals(value, other.value)) return false; return true; } @Override public String toString() { return ArrayUtils.toHexString(value); } public String getDescription() { StringBuilder sb = new StringBuilder(); if (value.length == 1) // Assume an MS/TP address sb.append(getMstpAddress() & 0xff); else if (value.length == 6) // Assume an I/P address sb.append(toIpPortString()); else sb.append(toString()); return sb.toString(); } }