001/** 002 * Copyright (c) 2014-2015 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; 013 014import com.digi.xbee.api.connection.IConnectionInterface; 015import com.digi.xbee.api.connection.serial.SerialPortParameters; 016import com.digi.xbee.api.exceptions.InterfaceNotOpenException; 017import com.digi.xbee.api.exceptions.OperationNotSupportedException; 018import com.digi.xbee.api.exceptions.TimeoutException; 019import com.digi.xbee.api.exceptions.XBeeDeviceException; 020import com.digi.xbee.api.exceptions.XBeeException; 021import com.digi.xbee.api.listeners.IExplicitDataReceiveListener; 022import com.digi.xbee.api.models.APIOutputMode; 023import com.digi.xbee.api.models.AssociationIndicationStatus; 024import com.digi.xbee.api.models.ExplicitXBeeMessage; 025import com.digi.xbee.api.models.XBee16BitAddress; 026import com.digi.xbee.api.models.XBee64BitAddress; 027import com.digi.xbee.api.models.XBeeProtocol; 028import com.digi.xbee.api.models.XBeeTransmitOptions; 029import com.digi.xbee.api.packet.XBeePacket; 030import com.digi.xbee.api.packet.common.ExplicitAddressingPacket; 031import com.digi.xbee.api.utils.HexUtils; 032 033/** 034 * This class represents a local ZigBee device. 035 * 036 * @see XBeeDevice 037 * @see DigiMeshDevice 038 * @see DigiPointDevice 039 * @see Raw802Device 040 */ 041public class ZigBeeDevice extends XBeeDevice { 042 043 /** 044 * Class constructor. Instantiates a new {@code ZigBeeDevice} object in the 045 * given port name and baud rate. 046 * 047 * @param port Serial port name where ZigBee device is attached to. 048 * @param baudRate Serial port baud rate to communicate with the device. 049 * Other connection parameters will be set as default (8 050 * data bits, 1 stop bit, no parity, no flow control). 051 * 052 * @throws IllegalArgumentException if {@code baudRate < 0}. 053 * @throws NullPointerException if {@code port == null}. 054 */ 055 public ZigBeeDevice(String port, int baudRate) { 056 this(XBee.createConnectiontionInterface(port, baudRate)); 057 } 058 059 /** 060 * Class constructor. Instantiates a new {@code ZigBeeDevice} object in the 061 * given serial port name and settings. 062 * 063 * @param port Serial port name where ZigBee device is attached to. 064 * @param baudRate Serial port baud rate to communicate with the device. 065 * @param dataBits Serial port data bits. 066 * @param stopBits Serial port data bits. 067 * @param parity Serial port data bits. 068 * @param flowControl Serial port data bits. 069 * 070 * @throws IllegalArgumentException if {@code baudRate < 0} or 071 * if {@code dataBits < 0} or 072 * if {@code stopBits < 0} or 073 * if {@code parity < 0} or 074 * if {@code flowControl < 0}. 075 * @throws NullPointerException if {@code port == null}. 076 */ 077 public ZigBeeDevice(String port, int baudRate, int dataBits, int stopBits, int parity, int flowControl) { 078 this(port, new SerialPortParameters(baudRate, dataBits, stopBits, parity, flowControl)); 079 } 080 081 /** 082 * Class constructor. Instantiates a new {@code ZigBeeDevice} object in the 083 * given serial port name and parameters. 084 * 085 * @param port Serial port name where ZigBee device is attached to. 086 * @param serialPortParameters Object containing the serial port parameters. 087 * 088 * @throws NullPointerException if {@code port == null} or 089 * if {@code serialPortParameters == null}. 090 * 091 * @see com.digi.xbee.api.connection.serial.SerialPortParameters 092 */ 093 public ZigBeeDevice(String port, SerialPortParameters serialPortParameters) { 094 this(XBee.createConnectiontionInterface(port, serialPortParameters)); 095 } 096 097 /** 098 * Class constructor. Instantiates a new {@code ZigBeeDevice} object with the 099 * given connection interface. 100 * 101 * @param connectionInterface The connection interface with the physical 102 * ZigBee device. 103 * 104 * @throws NullPointerException if {@code connectionInterface == null} 105 * 106 * @see com.digi.xbee.api.connection.IConnectionInterface 107 */ 108 public ZigBeeDevice(IConnectionInterface connectionInterface) { 109 super(connectionInterface); 110 } 111 112 /* 113 * (non-Javadoc) 114 * @see com.digi.xbee.api.XBeeDevice#open() 115 */ 116 @Override 117 public void open() throws XBeeException { 118 super.open(); 119 if (xbeeProtocol != XBeeProtocol.ZIGBEE) 120 throw new XBeeDeviceException("XBee device is not a " + getXBeeProtocol().getDescription() + " device, it is a " + xbeeProtocol.getDescription() + " device."); 121 } 122 123 /* 124 * (non-Javadoc) 125 * @see com.digi.xbee.api.XBeeDevice#getNetwork() 126 */ 127 @Override 128 public XBeeNetwork getNetwork() { 129 if (!isOpen()) 130 throw new InterfaceNotOpenException(); 131 if (network == null) 132 network = new ZigBeeNetwork(this); 133 return network; 134 } 135 136 /* 137 * (non-Javadoc) 138 * @see com.digi.xbee.api.XBeeDevice#getXBeeProtocol() 139 */ 140 @Override 141 public XBeeProtocol getXBeeProtocol() { 142 return XBeeProtocol.ZIGBEE; 143 } 144 145 /* 146 * (non-Javadoc) 147 * @see com.digi.xbee.api.XBeeDevice#sendDataAsync(com.digi.xbee.api.models.XBee64BitAddress, com.digi.xbee.api.models.XBee16BitAddress, byte[]) 148 */ 149 @Override 150 public void sendDataAsync(XBee64BitAddress address64Bit, XBee16BitAddress address16bit, byte[] data) throws XBeeException { 151 super.sendDataAsync(address64Bit, address16bit, data); 152 } 153 154 /* 155 * (non-Javadoc) 156 * @see com.digi.xbee.api.XBeeDevice#sendData(com.digi.xbee.api.models.XBee64BitAddress, com.digi.xbee.api.models.XBee16BitAddress, byte[]) 157 */ 158 @Override 159 public void sendData(XBee64BitAddress address64Bit, XBee16BitAddress address16bit, byte[] data) throws TimeoutException, XBeeException { 160 super.sendData(address64Bit, address16bit, data); 161 } 162 163 /* 164 * (non-Javadoc) 165 * @see com.digi.xbee.api.AbstractXBeeDevice#getAssociationIndicationStatus() 166 */ 167 @Override 168 public AssociationIndicationStatus getAssociationIndicationStatus() throws TimeoutException, XBeeException { 169 return super.getAssociationIndicationStatus(); 170 } 171 172 /* 173 * (non-Javadoc) 174 * @see com.digi.xbee.api.AbstractXBeeDevice#forceDisassociate() 175 */ 176 @Override 177 public void forceDisassociate() throws TimeoutException, XBeeException { 178 super.forceDisassociate(); 179 } 180 181 /* 182 * (non-Javadoc) 183 * @see com.digi.xbee.api.XBeeDevice#readExplicitData() 184 */ 185 @Override 186 public ExplicitXBeeMessage readExplicitData() { 187 return super.readExplicitData(); 188 } 189 190 /* 191 * (non-Javadoc) 192 * @see com.digi.xbee.api.XBeeDevice#readExplicitData(int) 193 */ 194 @Override 195 public ExplicitXBeeMessage readExplicitData(int timeout) { 196 return super.readExplicitData(timeout); 197 } 198 199 /* 200 * (non-Javadoc) 201 * @see com.digi.xbee.api.XBeeDevice#readExplicitDataFrom(com.digi.xbee.api.RemoteXBeeDevice) 202 */ 203 @Override 204 public ExplicitXBeeMessage readExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice) { 205 return super.readExplicitDataFrom(remoteXBeeDevice); 206 } 207 208 /* 209 * (non-Javadoc) 210 * @see com.digi.xbee.api.XBeeDevice#readExplicitDataFrom(com.digi.xbee.api.RemoteXBeeDevice, int) 211 */ 212 @Override 213 public ExplicitXBeeMessage readExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) { 214 return super.readExplicitDataFrom(remoteXBeeDevice, timeout); 215 } 216 217 /* 218 * (non-Javadoc) 219 * @see com.digi.xbee.api.AbstractXBeeDevice#addExplicitDataListener(com.digi.xbee.api.listeners.IExplicitDataReceiveListener) 220 */ 221 @Override 222 public void addExplicitDataListener(IExplicitDataReceiveListener listener) { 223 super.addExplicitDataListener(listener); 224 } 225 226 /* 227 * (non-Javadoc) 228 * @see com.digi.xbee.api.AbstractXBeeDevice#removeExplicitDataListener(com.digi.xbee.api.listeners.IExplicitDataReceiveListener) 229 */ 230 @Override 231 public void removeExplicitDataListener(IExplicitDataReceiveListener listener) { 232 super.removeExplicitDataListener(listener); 233 } 234 235 /* 236 * (non-Javadoc) 237 * @see com.digi.xbee.api.XBeeDevice#getAPIOutputMode() 238 */ 239 @Override 240 public APIOutputMode getAPIOutputMode() throws TimeoutException, XBeeException { 241 return super.getAPIOutputMode(); 242 } 243 244 /* 245 * (non-Javadoc) 246 * @see com.digi.xbee.api.XBeeDevice#setAPIOutputMode(com.digi.xbee.api.models.APIOutputMode) 247 */ 248 @Override 249 public void setAPIOutputMode(APIOutputMode apiOutputMode) throws TimeoutException, XBeeException { 250 super.setAPIOutputMode(apiOutputMode); 251 } 252 253 /* 254 * (non-Javadoc) 255 * @see com.digi.xbee.api.XBeeDevice#sendExplicitData(com.digi.xbee.api.RemoteXBeeDevice, int, int, int, int, byte[]) 256 */ 257 @Override 258 public void sendExplicitData(RemoteXBeeDevice remoteXBeeDevice, int sourceEndpoint, int destEndpoint, int clusterID, 259 int profileID, byte[] data) throws TimeoutException, XBeeException { 260 super.sendExplicitData(remoteXBeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data); 261 } 262 263 /* 264 * (non-Javadoc) 265 * @see com.digi.xbee.api.XBeeDevice#sendExplicitData(com.digi.xbee.api.models.XBee64BitAddress, com.digi.xbee.api.models.XBee16BitAddress, int, int, int, int, byte[]) 266 */ 267 @Override 268 public void sendExplicitData(XBee64BitAddress address64Bit, XBee16BitAddress address16bit, int sourceEndpoint, int destEndpoint, 269 int clusterID, int profileID, byte[] data) throws TimeoutException, XBeeException { 270 super.sendExplicitData(address64Bit, address16bit, sourceEndpoint, destEndpoint, clusterID, profileID, data); 271 } 272 273 /* 274 * (non-Javadoc) 275 * @see com.digi.xbee.api.XBeeDevice#sendBroadcastExplicitData(int, int, int, int, byte[]) 276 */ 277 @Override 278 public void sendBroadcastExplicitData(int sourceEndpoint, int destEndpoint, int clusterID, int profileID, 279 byte[] data) throws TimeoutException, XBeeException { 280 super.sendBroadcastExplicitData(sourceEndpoint, destEndpoint, clusterID, profileID, data); 281 } 282 283 /* 284 * (non-Javadoc) 285 * @see com.digi.xbee.api.XBeeDevice#sendExplicitDataAsync(com.digi.xbee.api.RemoteXBeeDevice, int, int, int, int, byte[]) 286 */ 287 @Override 288 public void sendExplicitDataAsync(RemoteXBeeDevice xbeeDevice, int sourceEndpoint, int destEndpoint, int clusterID, 289 int profileID, byte[] data) throws XBeeException { 290 super.sendExplicitDataAsync(xbeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data); 291 } 292 293 /* 294 * (non-Javadoc) 295 * @see com.digi.xbee.api.XBeeDevice#sendExplicitDataAsync(com.digi.xbee.api.models.XBee64BitAddress, com.digi.xbee.api.models.XBee16BitAddress, int, int, int, int, byte[]) 296 */ 297 @Override 298 public void sendExplicitDataAsync(XBee64BitAddress address64Bit, XBee16BitAddress address16Bit, int sourceEndpoint, 299 int destEndpoint, int clusterID, int profileID, byte[] data) throws XBeeException { 300 super.sendExplicitDataAsync(address64Bit, address16Bit, sourceEndpoint, destEndpoint, clusterID, profileID, data); 301 } 302 303 /** 304 * Sends a multicast transmission with the provided data to the given 305 * group ID. 306 * 307 * <p>This method blocks till a success or error response arrives or the 308 * configured receive timeout expires.</p> 309 * 310 * <p>The receive timeout is configured using the setReceiveTimeout method 311 * and can be consulted with getReceiveTimeout method.</p> 312 * 313 * @param groupID 16-bit address of the destination group ID. 314 * @param sourceEndpoint Source endpoint for the transmission. 315 * @param destEndpoint Destination endpoint for the transmission. 316 * @param clusterID Cluster ID used in the transmission. 317 * @param profileID Profile ID used in the transmission. 318 * @param data Byte array containing the data to be sent. 319 * 320 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 321 * if {@code sourceEndpoint > 0xFF} or 322 * if {@code destEndpoint < 0} or 323 * if {@code destEndpoint > 0xFF} or 324 * if {@code clusterID < 0} or 325 * if {@code clusterID > 0xFFFF} or 326 * if {@code profileID < 0} or 327 * if {@code profileID > 0xFFFF}. 328 * @throws InterfaceNotOpenException if this device connection is not open. 329 * @throws NullPointerException if {@code groupID == null} or 330 * if {@code data == null}. 331 * @throws TimeoutException if there is a timeout sending the data. 332 * @throws XBeeException if there is any other XBee related exception. 333 * 334 * @see #sendMulticastDataAsync(XBee16BitAddress, int, int, int, int, byte[]) 335 * @see #getReceiveTimeout() 336 * @see #setReceiveTimeout(int) 337 * @see com.digi.xbee.api.models.XBee16BitAddress 338 */ 339 public void sendMulticastData(XBee16BitAddress groupID, int sourceEndpoint, int destEndpoint, int clusterID, 340 int profileID, byte[] data) throws XBeeException { 341 // Verify the parameters are not null, if they are null, throw an exception. 342 if (groupID == null) 343 throw new NullPointerException("Destination group ID cannot be null"); 344 if (data == null) 345 throw new NullPointerException("Data cannot be null."); 346 if (sourceEndpoint < 0 || sourceEndpoint > 0xFF) 347 throw new IllegalArgumentException("Source endpoint must be between 0 and 0xFF."); 348 if (destEndpoint < 0 || destEndpoint > 0xFF) 349 throw new IllegalArgumentException("Destination endpoint must be between 0 and 0xFF."); 350 if (clusterID < 0 || clusterID > 0xFFFF) 351 throw new IllegalArgumentException("Cluster ID must be between 0 and 0xFFFF."); 352 if (profileID < 0 || profileID > 0xFFFF) 353 throw new IllegalArgumentException("Profile ID must be between 0 and 0xFFFF."); 354 355 // Check if device is remote. 356 if (isRemote()) 357 throw new OperationNotSupportedException("Cannot send multicast data to a remote device from a remote device."); 358 359 logger.debug(toString() + "Sending multicast data to {} [{} - {} - {} - {}] >> {}.", groupID, 360 HexUtils.integerToHexString(sourceEndpoint, 1), HexUtils.integerToHexString(destEndpoint, 1), 361 HexUtils.integerToHexString(clusterID, 2), HexUtils.integerToHexString(profileID, 2), 362 HexUtils.prettyHexString(data)); 363 364 XBeePacket xbeePacket = new ExplicitAddressingPacket(getNextFrameID(), XBee64BitAddress.UNKNOWN_ADDRESS, 365 groupID, sourceEndpoint, destEndpoint, clusterID, profileID, 0, XBeeTransmitOptions.ENABLE_MULTICAST, data); 366 sendAndCheckXBeePacket(xbeePacket, false); 367 } 368 369 /** 370 * Sends a multicast asynchronous transmission with the provided data to 371 * the given group ID. 372 * 373 * <p>Asynchronous transmissions do not wait for answer from the remote 374 * device or for transmit status packet.</p> 375 * 376 * @param groupID 16-bit address of the destination group ID. 377 * @param sourceEndpoint Source endpoint for the transmission. 378 * @param destEndpoint Destination endpoint for the transmission. 379 * @param clusterID Cluster ID used in the transmission. 380 * @param profileID Profile ID used in the transmission. 381 * @param data Byte array containing the data to be sent. 382 * 383 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 384 * if {@code sourceEndpoint > 0xFF} or 385 * if {@code destEndpoint < 0} or 386 * if {@code destEndpoint > 0xFF} or 387 * if {@code clusterID < 0} or 388 * if {@code clusterID > 0xFFFF} or 389 * if {@code profileID < 0} or 390 * if {@code profileID > 0xFFFF}. 391 * @throws InterfaceNotOpenException if this device connection is not open. 392 * @throws NullPointerException if {@code groupID == null} or 393 * if {@code data == null}. 394 * @throws XBeeException if there is any other XBee related exception. 395 * 396 * @see #sendMulticastData(XBee16BitAddress, int, int, int, int, byte[]) 397 * @see com.digi.xbee.api.models.XBee64BitAddress 398 */ 399 public void sendMulticastDataAsync(XBee16BitAddress groupID, int sourceEndpoint, int destEndpoint, int clusterID, 400 int profileID, byte[] data) throws XBeeException { 401 // Verify the parameters are not null, if they are null, throw an exception. 402 if (groupID == null) 403 throw new NullPointerException("Destination group ID cannot be null"); 404 if (data == null) 405 throw new NullPointerException("Data cannot be null."); 406 if (sourceEndpoint < 0 || sourceEndpoint > 0xFF) 407 throw new IllegalArgumentException("Source endpoint must be between 0 and 0xFF."); 408 if (destEndpoint < 0 || destEndpoint > 0xFF) 409 throw new IllegalArgumentException("Destination endpoint must be between 0 and 0xFF."); 410 if (clusterID < 0 || clusterID > 0xFFFF) 411 throw new IllegalArgumentException("Cluster ID must be between 0 and 0xFFFF."); 412 if (profileID < 0 || profileID > 0xFFFF) 413 throw new IllegalArgumentException("Profile ID must be between 0 and 0xFFFF."); 414 415 // Check if device is remote. 416 if (isRemote()) 417 throw new OperationNotSupportedException("Cannot send multicast data to a remote device from a remote device."); 418 419 logger.debug(toString() + "Sending multicast data asynchronously to {} [{} - {} - {} - {}] >> {}.", groupID, 420 HexUtils.integerToHexString(sourceEndpoint, 1), HexUtils.integerToHexString(destEndpoint, 1), 421 HexUtils.integerToHexString(clusterID, 2), HexUtils.integerToHexString(profileID, 2), 422 HexUtils.prettyHexString(data)); 423 424 XBeePacket xbeePacket = new ExplicitAddressingPacket(getNextFrameID(), XBee64BitAddress.UNKNOWN_ADDRESS, 425 groupID, sourceEndpoint, destEndpoint, clusterID, profileID, 0, XBeeTransmitOptions.ENABLE_MULTICAST, data); 426 sendAndCheckXBeePacket(xbeePacket, true); 427 } 428}