001/** 002 * Copyright 2017, Digi International Inc. 003 * 004 * This Source Code Form is subject to the terms of the Mozilla Public 005 * License, v. 2.0. If a copy of the MPL was not distributed with this 006 * file, you can obtain one at http://mozilla.org/MPL/2.0/. 007 * 008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 015 */ 016package com.digi.xbee.api.models; 017 018import java.util.Arrays; 019 020import com.digi.xbee.api.utils.HexUtils; 021 022/** 023 * This class represents a 16-bit network address. 024 * 025 * <p>This address is only applicable for:</p> 026 * <ul> 027 * <li>802.15.4</li> 028 * <li>ZigBee</li> 029 * <li>ZNet 2.5</li> 030 * <li>XTend (Legacy)</li> 031 * </ul> 032 * 033 * <p>DigiMesh and Point-to-Multipoint protocols don't support 16-bit 034 * addressing.</p> 035 * 036 * <p>Each device has its own 16-bit address which is unique in the network. 037 * It is automatically assigned when the radio joins the network for ZigBee 038 * and ZNet 2.5, and manually configured in 802.15.4 radios.</p> 039 * 040 */ 041public final class XBee16BitAddress { 042 043 // Constants 044 /** 045 * 16-bit address reserved for the coordinator (value: 0000). 046 */ 047 public static final XBee16BitAddress COORDINATOR_ADDRESS = new XBee16BitAddress("0000"); 048 /** 049 * 16-bit broadcast address (value: FFFF). 050 */ 051 public static final XBee16BitAddress BROADCAST_ADDRESS = new XBee16BitAddress("FFFF"); 052 /** 053 * 16-bit unknown address (value: FFFE). 054 */ 055 public static final XBee16BitAddress UNKNOWN_ADDRESS = new XBee16BitAddress("FFFE"); 056 057 /** 058 * Pattern for the 16-bit address string: {@value}. 059 */ 060 private static final String XBEE_16_BIT_ADDRESS_PATTERN = "(0[xX])?[0-9a-fA-F]{1,4}"; 061 062 private static final int HASH_SEED = 23; 063 064 // Variables 065 private final byte[] address; 066 067 /** 068 * Class constructor. Instantiates a new object of type 069 * {@code XBee16BitAddress} with the given parameters. 070 * 071 * @param hsb High significant byte of the address. 072 * @param lsb Low significant byte of the address. 073 * 074 * @throws IllegalArgumentException if {@code hsb > 255} or 075 * if {@code hsb < 0} or 076 * if {@code lsb > 255} or 077 * if {@code lsb < 0}. 078 */ 079 public XBee16BitAddress(int hsb, int lsb) { 080 if (hsb > 255 || hsb < 0) 081 throw new IllegalArgumentException("HSB must be between 0 and 255."); 082 if (lsb > 255 || lsb < 0) 083 throw new IllegalArgumentException("LSB must be between 0 and 255."); 084 085 address = new byte[2]; 086 address[0] = (byte) hsb; 087 address[1] = (byte) lsb; 088 } 089 090 /** 091 * Class constructor. Instantiates a new object of type 092 * {@code XBee16BitAddress} with the given parameters. 093 * 094 * @param address The 16-bit address as byte array. 095 * 096 * @throws IllegalArgumentException if {@code address.length < 1} or 097 * if {@code address.length > 2}. 098 * @throws NullPointerException if {@code address == null}. 099 */ 100 public XBee16BitAddress(byte[] address) { 101 if (address == null) 102 throw new NullPointerException("Address cannot be null."); 103 if (address.length < 1) 104 throw new IllegalArgumentException("Address must contain at least 1 byte."); 105 if (address.length > 2) 106 throw new IllegalArgumentException("Address cannot contain more than 2 bytes."); 107 108 // Check array size. 109 this.address = new byte[2]; 110 int diff = this.address.length - address.length; 111 for (int i = 0; i < diff; i++) 112 this.address[i] = 0; 113 for (int i = diff; i < this.address.length; i++) 114 this.address[i] = address[i - diff]; 115 } 116 117 /** 118 * Class constructor. Instantiates a new object of type 119 * {@code XBee16BitAddress} with the given parameters. 120 * 121 * <p>The string must be the hexadecimal representation of a 16-bit 122 * address.</p> 123 * 124 * @param address String containing the 16-bit address. 125 * 126 * @throws IllegalArgumentException if {@code address.length() < 1} or 127 * if {@code address} contains 128 * non-hexadecimal characters and is longer 129 * than 8 bytes. 130 * @throws NullPointerException if {@code address == null}. 131 */ 132 public XBee16BitAddress(String address) { 133 if (address == null) 134 throw new NullPointerException("Address cannot be null."); 135 if (address.length() < 1) 136 throw new IllegalArgumentException("Address must contain at least 1 character."); 137 if (!address.matches(XBEE_16_BIT_ADDRESS_PATTERN)) 138 throw new IllegalArgumentException("Address must follow this pattern: (0x)XXXX."); 139 140 // Convert the string into a byte array. 141 byte[] byteAddress = HexUtils.hexStringToByteArray(address); 142 // Check array size. 143 this.address = new byte[2]; 144 int diff = this.address.length - byteAddress.length; 145 for (int i = 0; i < diff; i++) 146 this.address[i] = 0; 147 for (int i = diff; i < this.address.length; i++) 148 this.address[i] = byteAddress[i - diff]; 149 } 150 151 /** 152 * Returns the address high significant byte. 153 * 154 * @return Address high significant byte. 155 */ 156 public int getHsb() { 157 return address[0]; 158 } 159 160 /** 161 * Returns the address low significant byte. 162 * 163 * @return Address low significant byte. 164 */ 165 public int getLsb() { 166 return address[1]; 167 } 168 169 /** 170 * Returns the 16-bit address value in byte array format. 171 * 172 * @return Address value as byte array. 173 */ 174 public byte[] getValue() { 175 return Arrays.copyOf(address, address.length); 176 } 177 178 /* 179 * (non-Javadoc) 180 * @see java.lang.Object#equals(java.lang.Object) 181 */ 182 @Override 183 public boolean equals(Object obj) { 184 if (!(obj instanceof XBee16BitAddress)) 185 return false; 186 XBee16BitAddress addr = (XBee16BitAddress)obj; 187 return Arrays.equals(addr.getValue(), getValue()); 188 } 189 190 /* 191 * (non-Javadoc) 192 * @see java.lang.Object#hashCode() 193 */ 194 @Override 195 public int hashCode() { 196 int hash = HASH_SEED; 197 for (byte b:getValue()) 198 hash = hash * (hash + b); 199 return hash; 200 } 201 202 /* 203 * (non-Javadoc) 204 * @see java.lang.Object#toString() 205 */ 206 @Override 207 public String toString() { 208 return HexUtils.byteArrayToHexString(address); 209 } 210}