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