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 java.io.IOException; 015 016import com.digi.xbee.api.connection.DataReader; 017import com.digi.xbee.api.connection.IConnectionInterface; 018import com.digi.xbee.api.connection.serial.SerialPortParameters; 019import com.digi.xbee.api.exceptions.ATCommandException; 020import com.digi.xbee.api.exceptions.InterfaceAlreadyOpenException; 021import com.digi.xbee.api.exceptions.InterfaceNotOpenException; 022import com.digi.xbee.api.exceptions.InvalidOperatingModeException; 023import com.digi.xbee.api.exceptions.OperationNotSupportedException; 024import com.digi.xbee.api.exceptions.TimeoutException; 025import com.digi.xbee.api.exceptions.XBeeException; 026import com.digi.xbee.api.listeners.IIOSampleReceiveListener; 027import com.digi.xbee.api.listeners.IModemStatusReceiveListener; 028import com.digi.xbee.api.listeners.IPacketReceiveListener; 029import com.digi.xbee.api.listeners.IDataReceiveListener; 030import com.digi.xbee.api.models.APIOutputMode; 031import com.digi.xbee.api.models.ATCommand; 032import com.digi.xbee.api.models.ATCommandResponse; 033import com.digi.xbee.api.models.ExplicitXBeeMessage; 034import com.digi.xbee.api.models.ModemStatusEvent; 035import com.digi.xbee.api.models.OperatingMode; 036import com.digi.xbee.api.models.XBee16BitAddress; 037import com.digi.xbee.api.models.XBee64BitAddress; 038import com.digi.xbee.api.models.XBeeMessage; 039import com.digi.xbee.api.models.XBeePacketsQueue; 040import com.digi.xbee.api.models.XBeeProtocol; 041import com.digi.xbee.api.models.XBeeTransmitOptions; 042import com.digi.xbee.api.packet.APIFrameType; 043import com.digi.xbee.api.packet.XBeeAPIPacket; 044import com.digi.xbee.api.packet.XBeePacket; 045import com.digi.xbee.api.packet.common.ExplicitAddressingPacket; 046import com.digi.xbee.api.packet.common.ExplicitRxIndicatorPacket; 047import com.digi.xbee.api.packet.common.ReceivePacket; 048import com.digi.xbee.api.packet.common.TransmitPacket; 049import com.digi.xbee.api.packet.raw.RX16Packet; 050import com.digi.xbee.api.packet.raw.RX64Packet; 051import com.digi.xbee.api.packet.raw.TX64Packet; 052import com.digi.xbee.api.utils.HexUtils; 053 054/** 055 * This class represents a local XBee device. 056 * 057 * @see DigiMeshDevice 058 * @see DigiPointDevice 059 * @see Raw802Device 060 * @see ZigBeeDevice 061 */ 062public class XBeeDevice extends AbstractXBeeDevice { 063 064 // Constants. 065 private static int TIMEOUT_RESET = 5000; 066 private static int TIMEOUT_READ_PACKET = 3000; 067 068 private static String COMMAND_MODE_CHAR = "+"; 069 private static String COMMAND_MODE_OK = "OK\r"; 070 071 // Variables. 072 protected XBeeNetwork network; 073 074 private Object resetLock = new Object(); 075 076 private boolean modemStatusReceived = false; 077 078 /** 079 * Class constructor. Instantiates a new {@code XBeeDevice} object 080 * physically connected to the given port name and configured at the 081 * provided baud rate. 082 * 083 * @param port Serial port name where XBee device is attached to. 084 * @param baudRate Serial port baud rate to communicate with the device. 085 * Other connection parameters will be set as default (8 086 * data bits, 1 stop bit, no parity, no flow control). 087 * 088 * @throws IllegalArgumentException if {@code baudRate < 0}. 089 * @throws NullPointerException if {@code port == null}. 090 * 091 * @see #XBeeDevice(IConnectionInterface) 092 * @see #XBeeDevice(String, SerialPortParameters) 093 * @see #XBeeDevice(String, int, int, int, int, int) 094 */ 095 public XBeeDevice(String port, int baudRate) { 096 super(port, baudRate); 097 } 098 099 /** 100 * Class constructor. Instantiates a new {@code XBeeDevice} object 101 * physically connected to the given port name and configured to communicate 102 * with the provided serial settings. 103 * 104 * @param port Serial port name where XBee device is attached to. 105 * @param baudRate Serial port baud rate to communicate with the device. 106 * @param dataBits Serial port data bits. 107 * @param stopBits Serial port data bits. 108 * @param parity Serial port data bits. 109 * @param flowControl Serial port data bits. 110 * 111 * @throws IllegalArgumentException if {@code baudRate < 0} or 112 * if {@code dataBits < 0} or 113 * if {@code stopBits < 0} or 114 * if {@code parity < 0} or 115 * if {@code flowControl < 0}. 116 * @throws NullPointerException if {@code port == null}. 117 * 118 * @see #XBeeDevice(IConnectionInterface) 119 * @see #XBeeDevice(String, int) 120 * @see #XBeeDevice(String, SerialPortParameters) 121 */ 122 public XBeeDevice(String port, int baudRate, int dataBits, int stopBits, int parity, int flowControl) { 123 super(port, baudRate, dataBits, stopBits, parity, flowControl); 124 } 125 126 /** 127 * Class constructor. Instantiates a new {@code XBeeDevice} object 128 * physically connected to the given port name and configured to communicate 129 * with the provided serial settings. 130 * 131 * @param port Serial port name where XBee device is attached to. 132 * @param serialPortParameters Object containing the serial port parameters. 133 * 134 * @throws NullPointerException if {@code port == null} or 135 * if {@code serialPortParameters == null}. 136 * 137 * @see #XBeeDevice(IConnectionInterface) 138 * @see #XBeeDevice(String, int) 139 * @see #XBeeDevice(String, int, int, int, int, int) 140 * @see com.digi.xbee.api.connection.serial.SerialPortParameters 141 */ 142 public XBeeDevice(String port, SerialPortParameters serialPortParameters) { 143 super(port, serialPortParameters); 144 } 145 146 /** 147 * Class constructor. Instantiates a new {@code XBeeDevice} object with the 148 * given connection interface. 149 * 150 * @param connectionInterface The connection interface with the physical 151 * XBee device. 152 * 153 * @throws NullPointerException if {@code connectionInterface == null}. 154 * 155 * @see #XBeeDevice(String, int) 156 * @see #XBeeDevice(String, SerialPortParameters) 157 * @see #XBeeDevice(String, int, int, int, int, int) 158 * @see com.digi.xbee.api.connection.IConnectionInterface 159 */ 160 public XBeeDevice(IConnectionInterface connectionInterface) { 161 super(connectionInterface); 162 } 163 164 /** 165 * Opens the connection interface associated with this XBee device. 166 * 167 * <p>When opening the device an information reading process is 168 * automatically performed. This includes:</p> 169 * 170 * <ul> 171 * <li>64-bit address.</li> 172 * <li>Node Identifier.</li> 173 * <li>Hardware version.</li> 174 * <li>Firmware version.</li> 175 * <li>XBee device protocol.</li> 176 * <li>16-bit address (not for DigiMesh modules).</li> 177 * </ul> 178 * 179 * @throws InterfaceAlreadyOpenException if this device connection is 180 * already open. 181 * @throws XBeeException if there is any problem opening this device 182 * connection. 183 * 184 * @see #close() 185 * @see #isOpen() 186 */ 187 public void open() throws XBeeException { 188 logger.info(toString() + "Opening the connection interface..."); 189 190 // First, verify that the connection is not already open. 191 if (connectionInterface.isOpen()) 192 throw new InterfaceAlreadyOpenException(); 193 194 // Connect the interface. 195 connectionInterface.open(); 196 197 logger.info(toString() + "Connection interface open."); 198 199 // Initialize the data reader. 200 dataReader = new DataReader(connectionInterface, operatingMode, this); 201 dataReader.start(); 202 203 // Wait 10 milliseconds until the dataReader thread is started. 204 // This is because when the connection is opened immediately after 205 // closing it, there is sometimes a concurrency problem and the 206 // dataReader thread never dies. 207 try { 208 Thread.sleep(10); 209 } catch (InterruptedException e) {} 210 211 // Determine the operating mode of the XBee device if it is unknown. 212 if (operatingMode == OperatingMode.UNKNOWN) 213 operatingMode = determineOperatingMode(); 214 215 // Check if the operating mode is a valid and supported one. 216 if (operatingMode == OperatingMode.UNKNOWN) { 217 close(); 218 throw new InvalidOperatingModeException("Could not determine operating mode."); 219 } else if (operatingMode == OperatingMode.AT) { 220 close(); 221 throw new InvalidOperatingModeException(operatingMode); 222 } 223 224 // Read the device info (obtain its parameters and protocol). 225 try { 226 readDeviceInfo(); 227 } catch (ATCommandException e) { 228 throw new XBeeException("Error reading device information.", e); 229 } 230 } 231 232 /** 233 * Closes the connection interface associated with this XBee device. 234 * 235 * @see #isOpen() 236 * @see #open() 237 */ 238 public void close() { 239 // Stop XBee reader. 240 if (dataReader != null && dataReader.isRunning()) 241 dataReader.stopReader(); 242 // Close interface. 243 connectionInterface.close(); 244 logger.info(toString() + "Connection interface closed."); 245 } 246 247 /** 248 * Returns whether the connection interface associated to this device is 249 * already open. 250 * 251 * @return {@code true} if the interface is open, {@code false} otherwise. 252 * 253 * @see #close() 254 * @see #open() 255 */ 256 public boolean isOpen() { 257 if (connectionInterface != null) 258 return connectionInterface.isOpen(); 259 return false; 260 } 261 262 /** 263 * Always returns {@code false}, since this is always a local device. 264 * 265 * @return {@code false} since it is a local device. 266 */ 267 @Override 268 public boolean isRemote() { 269 return false; 270 } 271 272 /** 273 * Returns the network associated with this XBee device. 274 * 275 * @return The XBee network of the device. 276 * 277 * @throws InterfaceNotOpenException if this device connection is not open. 278 * 279 * @see XBeeNetwork 280 */ 281 public XBeeNetwork getNetwork() { 282 if (!isOpen()) 283 throw new InterfaceNotOpenException(); 284 285 if (network == null) 286 network = new XBeeNetwork(this); 287 return network; 288 } 289 290 /** 291 * Returns the Operating mode (AT, API or API escaped) of this XBee device. 292 * 293 * @return The operating mode of this XBee device. 294 * 295 * @see com.digi.xbee.api.models.OperatingMode 296 */ 297 @Override 298 public OperatingMode getOperatingMode() { 299 return super.getOperatingMode(); 300 } 301 302 /* 303 * (non-Javadoc) 304 * @see com.digi.xbee.api.AbstractXBeeDevice#getNextFrameID() 305 */ 306 @Override 307 protected int getNextFrameID() { 308 return super.getNextFrameID(); 309 } 310 311 /** 312 * Returns this XBee device configured timeout for receiving packets in 313 * synchronous operations. 314 * 315 * @return The current receive timeout in milliseconds. 316 * 317 * @see #setReceiveTimeout(int) 318 */ 319 public int getReceiveTimeout() { 320 return receiveTimeout; 321 } 322 323 /** 324 * Configures this XBee device timeout in milliseconds for receiving 325 * packets in synchronous operations. 326 * 327 * @param receiveTimeout The new receive timeout in milliseconds. 328 * 329 * @throws IllegalArgumentException if {@code receiveTimeout < 0}. 330 * 331 * @see #getReceiveTimeout() 332 */ 333 public void setReceiveTimeout(int receiveTimeout) { 334 if (receiveTimeout < 0) 335 throw new IllegalArgumentException("Receive timeout cannot be less than 0."); 336 337 this.receiveTimeout = receiveTimeout; 338 } 339 340 /** 341 * Determines the operating mode of this XBee device. 342 * 343 * @return The operating mode of the XBee device. 344 * 345 * @throws InterfaceNotOpenException if this device connection is not open. 346 * @throws OperationNotSupportedException if the packet is being sent from 347 * a remote device. 348 * 349 * @see com.digi.xbee.api.models.OperatingMode 350 */ 351 protected OperatingMode determineOperatingMode() throws OperationNotSupportedException { 352 try { 353 // Check if device is in API or API Escaped operating modes. 354 operatingMode = OperatingMode.API; 355 dataReader.setXBeeReaderMode(operatingMode); 356 357 ATCommandResponse response = sendATCommand(new ATCommand("AP")); 358 if (response.getResponse() != null && response.getResponse().length > 0) { 359 if (response.getResponse()[0] != OperatingMode.API.getID()) { 360 operatingMode = OperatingMode.API_ESCAPE; 361 dataReader.setXBeeReaderMode(operatingMode); 362 } 363 logger.debug(toString() + "Using {}.", operatingMode.getName()); 364 return operatingMode; 365 } 366 } catch (TimeoutException e) { 367 // Check if device is in AT operating mode. 368 operatingMode = OperatingMode.AT; 369 dataReader.setXBeeReaderMode(operatingMode); 370 371 try { 372 // It is necessary to wait at least 1 second to enter in 373 // command mode after sending any data to the device. 374 Thread.sleep(TIMEOUT_BEFORE_COMMAND_MODE); 375 // Try to enter in AT command mode, if so the module is in AT mode. 376 boolean success = enterATCommandMode(); 377 if (success) 378 return OperatingMode.AT; 379 } catch (TimeoutException e1) { 380 logger.error(e1.getMessage(), e1); 381 } catch (InvalidOperatingModeException e1) { 382 logger.error(e1.getMessage(), e1); 383 } catch (InterruptedException e1) { 384 logger.error(e1.getMessage(), e1); 385 } 386 } catch (InvalidOperatingModeException e) { 387 logger.error("Invalid operating mode", e); 388 } catch (IOException e) { 389 logger.error(e.getMessage(), e); 390 } 391 return OperatingMode.UNKNOWN; 392 } 393 394 /** 395 * Attempts to put this device in AT Command mode. Only valid if device is 396 * working in AT mode. 397 * 398 * @return {@code true} if the device entered in AT command mode, 399 * {@code false} otherwise. 400 * 401 * @throws InterfaceNotOpenException if this device connection is not open. 402 * @throws InvalidOperatingModeException if the operating mode cannot be 403 * determined or is not supported. 404 * @throws TimeoutException if the configured time for this device expires. 405 */ 406 private boolean enterATCommandMode() throws InvalidOperatingModeException, TimeoutException { 407 if (!connectionInterface.isOpen()) 408 throw new InterfaceNotOpenException(); 409 if (operatingMode != OperatingMode.AT) 410 throw new InvalidOperatingModeException("Invalid mode. Command mode can be only accessed while in AT mode."); 411 412 // Enter in AT command mode (send '+++'). The process waits 1,5 seconds for the 'OK\n'. 413 byte[] readData = new byte[256]; 414 try { 415 // Send the command mode sequence. 416 connectionInterface.writeData(COMMAND_MODE_CHAR.getBytes()); 417 connectionInterface.writeData(COMMAND_MODE_CHAR.getBytes()); 418 connectionInterface.writeData(COMMAND_MODE_CHAR.getBytes()); 419 420 // Wait some time to let the module generate a response. 421 Thread.sleep(TIMEOUT_ENTER_COMMAND_MODE); 422 423 // Read data from the device (it should answer with 'OK\r'). 424 int readBytes = connectionInterface.readData(readData); 425 if (readBytes < COMMAND_MODE_OK.length()) 426 throw new TimeoutException(); 427 428 // Check if the read data is 'OK\r'. 429 String readString = new String(readData, 0, readBytes); 430 if (!readString.contains(COMMAND_MODE_OK)) 431 return false; 432 433 // Read data was 'OK\r'. 434 return true; 435 } catch (IOException e) { 436 logger.error(e.getMessage(), e); 437 } catch (InterruptedException e) { 438 logger.error(e.getMessage(), e); 439 } 440 return false; 441 } 442 443 /* 444 * (non-Javadoc) 445 * @see com.digi.xbee.api.AbstractXBeeDevice#addPacketListener(com.digi.xbee.api.listeners.IPacketReceiveListener) 446 */ 447 @Override 448 public void addPacketListener(IPacketReceiveListener listener) { 449 super.addPacketListener(listener); 450 } 451 452 /* 453 * (non-Javadoc) 454 * @see com.digi.xbee.api.AbstractXBeeDevice#removePacketListener(com.digi.xbee.api.listeners.IPacketReceiveListener) 455 */ 456 @Override 457 public void removePacketListener(IPacketReceiveListener listener) { 458 super.removePacketListener(listener); 459 } 460 461 /* 462 * (non-Javadoc) 463 * @see com.digi.xbee.api.AbstractXBeeDevice#addDataListener(com.digi.xbee.api.listeners.IDataReceiveListener) 464 */ 465 @Override 466 public void addDataListener(IDataReceiveListener listener) { 467 super.addDataListener(listener); 468 } 469 470 /* 471 * (non-Javadoc) 472 * @see com.digi.xbee.api.AbstractXBeeDevice#removeDataListener(com.digi.xbee.api.listeners.IDataReceiveListener) 473 */ 474 @Override 475 public void removeDataListener(IDataReceiveListener listener) { 476 super.removeDataListener(listener); 477 } 478 479 /* 480 * (non-Javadoc) 481 * @see com.digi.xbee.api.AbstractXBeeDevice#addIOSampleListener(com.digi.xbee.api.listeners.IIOSampleReceiveListener) 482 */ 483 @Override 484 public void addIOSampleListener(IIOSampleReceiveListener listener) { 485 super.addIOSampleListener(listener); 486 } 487 488 /* 489 * (non-Javadoc) 490 * @see com.digi.xbee.api.AbstractXBeeDevice#removeIOSampleListener(com.digi.xbee.api.listeners.IIOSampleReceiveListener) 491 */ 492 @Override 493 public void removeIOSampleListener(IIOSampleReceiveListener listener) { 494 super.removeIOSampleListener(listener); 495 } 496 497 /* 498 * (non-Javadoc) 499 * @see com.digi.xbee.api.AbstractXBeeDevice#addModemStatusListener(com.digi.xbee.api.listeners.IModemStatusReceiveListener) 500 */ 501 @Override 502 public void addModemStatusListener(IModemStatusReceiveListener listener) { 503 super.addModemStatusListener(listener); 504 } 505 506 /* 507 * (non-Javadoc) 508 * @see com.digi.xbee.api.AbstractXBeeDevice#removeModemStatusListener(com.digi.xbee.api.listeners.IModemStatusReceiveListener) 509 */ 510 @Override 511 public void removeModemStatusListener(IModemStatusReceiveListener listener) { 512 super.removeModemStatusListener(listener); 513 } 514 515 /** 516 * Sends asynchronously the provided data to the XBee device of the network 517 * corresponding to the given 64-bit address. 518 * 519 * <p>Asynchronous transmissions do not wait for answer from the remote 520 * device or for transmit status packet.</p> 521 * 522 * @param address The 64-bit address of the XBee that will receive the data. 523 * @param data Byte array containing the data to be sent. 524 * 525 * @throws InterfaceNotOpenException if this device connection is not open. 526 * @throws NullPointerException if {@code address == null} or 527 * if {@code data == null}. 528 * @throws XBeeException if there is any XBee related exception. 529 * 530 * @see #sendData(RemoteXBeeDevice, byte[]) 531 * @see #sendData(XBee64BitAddress, byte[]) 532 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 533 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 534 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 535 * @see com.digi.xbee.api.models.XBee64BitAddress 536 */ 537 protected void sendDataAsync(XBee64BitAddress address, byte[] data) throws XBeeException { 538 // Verify the parameters are not null, if they are null, throw an exception. 539 if (address == null) 540 throw new NullPointerException("Address cannot be null"); 541 if (data == null) 542 throw new NullPointerException("Data cannot be null"); 543 544 // Check if device is remote. 545 if (isRemote()) 546 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 547 548 logger.debug(toString() + "Sending data asynchronously to {} >> {}.", address, HexUtils.prettyHexString(data)); 549 550 XBeePacket xbeePacket; 551 switch (getXBeeProtocol()) { 552 case RAW_802_15_4: 553 xbeePacket = new TX64Packet(getNextFrameID(), address, XBeeTransmitOptions.NONE, data); 554 break; 555 default: 556 xbeePacket = new TransmitPacket(getNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, 0, XBeeTransmitOptions.NONE, data); 557 } 558 sendAndCheckXBeePacket(xbeePacket, true); 559 } 560 561 /** 562 * Sends asynchronously the provided data to the XBee device of the network 563 * corresponding to the given 64-bit/16-bit address. 564 * 565 * <p>Asynchronous transmissions do not wait for answer from the remote 566 * device or for transmit status packet.</p> 567 * 568 * @param address64Bit The 64-bit address of the XBee that will receive the 569 * data. 570 * @param address16Bit The 16-bit address of the XBee that will receive the 571 * data. If it is unknown the 572 * {@code XBee16BitAddress.UNKNOWN_ADDRESS} must be 573 * used. 574 * @param data Byte array containing the data to be sent. 575 * 576 * @throws InterfaceNotOpenException if this device connection is not open. 577 * @throws NullPointerException if {@code address64Bit == null} or 578 * if {@code address16Bit == null} or 579 * if {@code data == null}. 580 * @throws XBeeException if a remote device is trying to send data or 581 * if there is any other XBee related exception. 582 * 583 * @see #sendData(RemoteXBeeDevice, byte[]) 584 * @see #sendData(XBee64BitAddress, byte[]) 585 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 586 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 587 * @see #sendDataAsync(XBee64BitAddress, byte[]) 588 * @see com.digi.xbee.api.models.XBee16BitAddress 589 * @see com.digi.xbee.api.models.XBee64BitAddress 590 */ 591 protected void sendDataAsync(XBee64BitAddress address64Bit, XBee16BitAddress address16Bit, byte[] data) throws XBeeException { 592 // Verify the parameters are not null, if they are null, throw an exception. 593 if (address64Bit == null) 594 throw new NullPointerException("64-bit address cannot be null"); 595 if (address16Bit == null) 596 throw new NullPointerException("16-bit address cannot be null"); 597 if (data == null) 598 throw new NullPointerException("Data cannot be null"); 599 600 // Check if device is remote. 601 if (isRemote()) 602 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 603 604 logger.debug(toString() + "Sending data asynchronously to {}[{}] >> {}.", 605 address64Bit, address16Bit, HexUtils.prettyHexString(data)); 606 607 XBeePacket xbeePacket = new TransmitPacket(getNextFrameID(), address64Bit, address16Bit, 0, XBeeTransmitOptions.NONE, data); 608 sendAndCheckXBeePacket(xbeePacket, true); 609 } 610 611 /** 612 * Sends the provided data to the provided XBee device asynchronously 613 * choosing the optimal send method depending on the protocol of the local 614 * XBee device. 615 * 616 * <p>Asynchronous transmissions do not wait for answer from the remote 617 * device or for transmit status packet.</p> 618 * 619 * @param remoteXBeeDevice The XBee device of the network that will receive the 620 * data. 621 * @param data Byte array containing the data to be sent. 622 * 623 * @throws InterfaceNotOpenException if this device connection is not open. 624 * @throws NullPointerException if {@code remoteXBeeDevice == null} or 625 * if {@code data == null}. 626 * @throws XBeeException if there is any XBee related exception. 627 * 628 * @see #sendData(RemoteXBeeDevice, byte[]) 629 * @see #sendData(XBee64BitAddress, byte[]) 630 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 631 * @see #sendDataAsync(XBee64BitAddress, byte[]) 632 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 633 * @see RemoteXBeeDevice 634 */ 635 public void sendDataAsync(RemoteXBeeDevice remoteXBeeDevice, byte[] data) throws XBeeException { 636 if (remoteXBeeDevice == null) 637 throw new NullPointerException("Remote XBee device cannot be null"); 638 639 switch (getXBeeProtocol()) { 640 case ZIGBEE: 641 case DIGI_POINT: 642 if (remoteXBeeDevice.get64BitAddress() != null && remoteXBeeDevice.get16BitAddress() != null) 643 sendDataAsync(remoteXBeeDevice.get64BitAddress(), remoteXBeeDevice.get16BitAddress(), data); 644 else 645 sendDataAsync(remoteXBeeDevice.get64BitAddress(), data); 646 break; 647 case RAW_802_15_4: 648 if (this instanceof Raw802Device) { 649 if (remoteXBeeDevice.get64BitAddress() != null) 650 ((Raw802Device)this).sendDataAsync(remoteXBeeDevice.get64BitAddress(), data); 651 else 652 ((Raw802Device)this).sendDataAsync(remoteXBeeDevice.get16BitAddress(), data); 653 } else 654 sendDataAsync(remoteXBeeDevice.get64BitAddress(), data); 655 break; 656 case DIGI_MESH: 657 default: 658 sendDataAsync(remoteXBeeDevice.get64BitAddress(), data); 659 } 660 } 661 662 /** 663 * Sends the provided data to the XBee device of the network corresponding 664 * to the given 64-bit address. 665 * 666 * <p>This method blocks till a success or error response arrives or the 667 * configured receive timeout expires.</p> 668 * 669 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 670 * method and can be consulted with {@code getReceiveTimeout} method.</p> 671 * 672 * <p>For non-blocking operations use the method 673 * {@link #sendDataAsync(XBee64BitAddress, byte[])}.</p> 674 * 675 * @param address The 64-bit address of the XBee that will receive the data. 676 * @param data Byte array containing the data to be sent. 677 * 678 * @throws InterfaceNotOpenException if this device connection is not open. 679 * @throws NullPointerException if {@code address == null} or 680 * if {@code data == null}. 681 * @throws TimeoutException if there is a timeout sending the data. 682 * @throws XBeeException if there is any other XBee related exception. 683 * 684 * @see #getReceiveTimeout() 685 * @see #setReceiveTimeout(int) 686 * @see #sendData(RemoteXBeeDevice, byte[]) 687 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 688 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 689 * @see #sendDataAsync(XBee64BitAddress, byte[]) 690 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 691 * @see com.digi.xbee.api.models.XBee64BitAddress 692 */ 693 protected void sendData(XBee64BitAddress address, byte[] data) throws TimeoutException, XBeeException { 694 // Verify the parameters are not null, if they are null, throw an exception. 695 if (address == null) 696 throw new NullPointerException("Address cannot be null"); 697 if (data == null) 698 throw new NullPointerException("Data cannot be null"); 699 700 // Check if device is remote. 701 if (isRemote()) 702 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 703 704 logger.debug(toString() + "Sending data to {} >> {}.", address, HexUtils.prettyHexString(data)); 705 706 XBeePacket xbeePacket; 707 switch (getXBeeProtocol()) { 708 case RAW_802_15_4: 709 xbeePacket = new TX64Packet(getNextFrameID(), address, XBeeTransmitOptions.NONE, data); 710 break; 711 default: 712 xbeePacket = new TransmitPacket(getNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, 0, XBeeTransmitOptions.NONE, data); 713 } 714 sendAndCheckXBeePacket(xbeePacket, false); 715 } 716 717 /** 718 * Sends the provided data to the XBee device of the network corresponding 719 * to the given 64-bit/16-bit address. 720 * 721 * <p>This method blocks till a success or error response arrives or the 722 * configured receive timeout expires.</p> 723 * 724 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 725 * method and can be consulted with {@code getReceiveTimeout} method.</p> 726 * 727 * <p>For non-blocking operations use the method 728 * {@link #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[])}.</p> 729 * 730 * @param address64Bit The 64-bit address of the XBee that will receive the 731 * data. 732 * @param address16Bit The 16-bit address of the XBee that will receive the 733 * data. If it is unknown the 734 * {@code XBee16BitAddress.UNKNOWN_ADDRESS} must be 735 * used. 736 * @param data Byte array containing the data to be sent. 737 * 738 * @throws InterfaceNotOpenException if this device connection is not open. 739 * @throws NullPointerException if {@code address64Bit == null} or 740 * if {@code address16Bit == null} or 741 * if {@code data == null}. 742 * @throws TimeoutException if there is a timeout sending the data. 743 * @throws XBeeException if a remote device is trying to send data or 744 * if there is any other XBee related exception. 745 * 746 * @see #getReceiveTimeout() 747 * @see #setReceiveTimeout(int) 748 * @see #sendData(RemoteXBeeDevice, byte[]) 749 * @see #sendData(XBee64BitAddress, byte[]) 750 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 751 * @see #sendDataAsync(XBee64BitAddress, byte[]) 752 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 753 * @see com.digi.xbee.api.models.XBee16BitAddress 754 * @see com.digi.xbee.api.models.XBee64BitAddress 755 */ 756 protected void sendData(XBee64BitAddress address64Bit, XBee16BitAddress address16Bit, byte[] data) throws TimeoutException, XBeeException { 757 // Verify the parameters are not null, if they are null, throw an exception. 758 if (address64Bit == null) 759 throw new NullPointerException("64-bit address cannot be null"); 760 if (address16Bit == null) 761 throw new NullPointerException("16-bit address cannot be null"); 762 if (data == null) 763 throw new NullPointerException("Data cannot be null"); 764 765 // Check if device is remote. 766 if (isRemote()) 767 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 768 769 logger.debug(toString() + "Sending data to {}[{}] >> {}.", 770 address64Bit, address16Bit, HexUtils.prettyHexString(data)); 771 772 XBeePacket xbeePacket = new TransmitPacket(getNextFrameID(), address64Bit, address16Bit, 0, XBeeTransmitOptions.NONE, data); 773 sendAndCheckXBeePacket(xbeePacket, false); 774 } 775 776 /** 777 * Sends the provided data to the given XBee device choosing the optimal 778 * send method depending on the protocol of the local XBee device. 779 * 780 * <p>This method blocks till a success or error response arrives or the 781 * configured receive timeout expires.</p> 782 * 783 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 784 * method and can be consulted with {@code getReceiveTimeout} method.</p> 785 * 786 * <p>For non-blocking operations use the method 787 * {@link #sendDataAsync(RemoteXBeeDevice, byte[])}.</p> 788 * 789 * @param remoteXBeeDevice The XBee device of the network that will receive 790 * the data. 791 * @param data Byte array containing the data to be sent. 792 * 793 * @throws InterfaceNotOpenException if this device connection is not open. 794 * @throws NullPointerException if {@code xbeeDevice == null} or 795 * if {@code data == null}. 796 * @throws TimeoutException if there is a timeout sending the data. 797 * @throws XBeeException if there is any other XBee related exception. 798 * 799 * @see #getReceiveTimeout() 800 * @see #setReceiveTimeout(int) 801 * @see #sendData(XBee64BitAddress, byte[]) 802 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 803 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 804 * @see #sendDataAsync(XBee64BitAddress, byte[]) 805 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 806 * @see com.digi.xbee.api.RemoteXBeeDevice 807 */ 808 public void sendData(RemoteXBeeDevice remoteXBeeDevice, byte[] data) throws TimeoutException, XBeeException { 809 if (remoteXBeeDevice == null) 810 throw new NullPointerException("Remote XBee device cannot be null"); 811 812 switch (getXBeeProtocol()) { 813 case ZIGBEE: 814 case DIGI_POINT: 815 if (remoteXBeeDevice.get64BitAddress() != null && remoteXBeeDevice.get16BitAddress() != null) 816 sendData(remoteXBeeDevice.get64BitAddress(), remoteXBeeDevice.get16BitAddress(), data); 817 else 818 sendData(remoteXBeeDevice.get64BitAddress(), data); 819 break; 820 case RAW_802_15_4: 821 if (this instanceof Raw802Device) { 822 if (remoteXBeeDevice.get64BitAddress() != null) 823 ((Raw802Device)this).sendData(remoteXBeeDevice.get64BitAddress(), data); 824 else 825 ((Raw802Device)this).sendData(remoteXBeeDevice.get16BitAddress(), data); 826 } else 827 sendData(remoteXBeeDevice.get64BitAddress(), data); 828 break; 829 case DIGI_MESH: 830 default: 831 sendData(remoteXBeeDevice.get64BitAddress(), data); 832 } 833 } 834 835 /** 836 * Sends the provided data to all the XBee nodes of the network (broadcast). 837 * 838 * <p>This method blocks till a success or error transmit status arrives or 839 * the configured receive timeout expires.</p> 840 * 841 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 842 * method and can be consulted with {@code getReceiveTimeout} method.</p> 843 * 844 * @param data Byte array containing the data to be sent. 845 * 846 * @throws InterfaceNotOpenException if this device connection is not open. 847 * @throws NullPointerException if {@code data == null}. 848 * @throws TimeoutException if there is a timeout sending the data. 849 * @throws XBeeException if there is any other XBee related exception. 850 * 851 * @see #getReceiveTimeout() 852 * @see #setReceiveTimeout(int) 853 */ 854 public void sendBroadcastData(byte[] data) throws TimeoutException, XBeeException { 855 sendData(XBee64BitAddress.BROADCAST_ADDRESS, data); 856 } 857 858 /** 859 * Sends asynchronously the provided data in application layer mode to the 860 * XBee device of the network corresponding to the given 64-bit address. 861 * Application layer mode means that you need to specify the application 862 * layer fields to be sent with the data. 863 * 864 * <p>Asynchronous transmissions do not wait for answer from the remote 865 * device or for transmit status packet.</p> 866 * 867 * @param address The 64-bit address of the XBee that will receive the data. 868 * @param sourceEndpoint Source endpoint for the transmission. 869 * @param destEndpoint Destination endpoint for the transmission. 870 * @param clusterID Cluster ID used in the transmission. 871 * @param profileID Profile ID used in the transmission. 872 * @param data Byte array containing the data to be sent. 873 * 874 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 875 * if {@code sourceEndpoint > 0xFF} or 876 * if {@code destEndpoint < 0} or 877 * if {@code destEndpoint > 0xFF} or 878 * if {@code clusterID < 0} or 879 * if {@code clusterID > 0xFFFF} or 880 * if {@code profileID < 0} or 881 * if {@code profileID > 0xFFFF}. 882 * @throws InterfaceNotOpenException if this device connection is not open. 883 * @throws NullPointerException if {@code address == null} or 884 * if {@code data == null}. 885 * @throws XBeeException if there is any other XBee related exception. 886 * 887 * @see #sendExplicitData(RemoteXBeeDevice, int, int, int, int, byte[]) 888 * @see #sendExplicitData(XBee64BitAddress, int, int, int, int, byte[]) 889 * @see #sendExplicitData(XBee64BitAddress, XBee16BitAddress, int, int, int, int, byte[]) 890 * @see #sendExplicitDataAsync(RemoteXBeeDevice, int, int, int, int, byte[]) 891 * @see #sendExplicitDataAsync(XBee64BitAddress, XBee16BitAddress, int, int, int, int, byte[]) 892 * @see com.digi.xbee.api.models.XBee64BitAddress 893 */ 894 protected void sendExplicitDataAsync(XBee64BitAddress address, int sourceEndpoint, int destEndpoint, int clusterID, 895 int profileID, byte[] data) throws XBeeException { 896 if (address == null) 897 throw new NullPointerException("Address cannot be null"); 898 if (data == null) 899 throw new NullPointerException("Data cannot be null."); 900 if (sourceEndpoint < 0 || sourceEndpoint > 0xFF) 901 throw new IllegalArgumentException("Source endpoint must be between 0 and 0xFF."); 902 if (destEndpoint < 0 || destEndpoint > 0xFF) 903 throw new IllegalArgumentException("Destination endpoint must be between 0 and 0xFF."); 904 if (clusterID < 0 || clusterID > 0xFFFF) 905 throw new IllegalArgumentException("Cluster ID must be between 0 and 0xFFFF."); 906 if (profileID < 0 || profileID > 0xFFFF) 907 throw new IllegalArgumentException("Profile ID must be between 0 and 0xFFFF."); 908 909 // Check if device is remote. 910 if (isRemote()) 911 throw new OperationNotSupportedException("Cannot send explicit data to a remote device from a remote device."); 912 913 logger.debug(toString() + "Sending explicit data asynchronously to {} [{} - {} - {} - {}] >> {}.", address, HexUtils.integerToHexString(sourceEndpoint, 1), 914 HexUtils.integerToHexString(destEndpoint, 1), HexUtils.integerToHexString(clusterID, 2), 915 HexUtils.integerToHexString(profileID, 2), HexUtils.prettyHexString(data)); 916 917 XBeePacket xbeePacket = new ExplicitAddressingPacket(getNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, sourceEndpoint, destEndpoint, clusterID, profileID, 0, XBeeTransmitOptions.NONE, data); 918 sendAndCheckXBeePacket(xbeePacket, true); 919 } 920 921 /** 922 * Sends asynchronously the provided data in application layer mode to the 923 * XBee device of the network corresponding to the given 64-bit/16-bit 924 * address. Application layer mode means that you need to specify the 925 * application layer fields to be sent with the data. 926 * 927 * <p>Asynchronous transmissions do not wait for answer from the remote 928 * device or for transmit status packet.</p> 929 * 930 * @param address64Bit The 64-bit address of the XBee that will receive the 931 * data. 932 * @param address16Bit The 16-bit address of the XBee that will receive the 933 * data. If it is unknown the 934 * {@code XBee16BitAddress.UNKNOWN_ADDRESS} must be 935 * used. 936 * @param sourceEndpoint Source endpoint for the transmission. 937 * @param destEndpoint Destination endpoint for the transmission. 938 * @param clusterID Cluster ID used in the transmission. 939 * @param profileID Profile ID used in the transmission. 940 * @param data Byte array containing the data to be sent. 941 * 942 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 943 * if {@code sourceEndpoint > 0xFF} or 944 * if {@code destEndpoint < 0} or 945 * if {@code destEndpoint > 0xFF} or 946 * if {@code clusterID < 0} or 947 * if {@code clusterID > 0xFFFF} or 948 * if {@code profileID < 0} or 949 * if {@code profileID > 0xFFFF}. 950 * @throws InterfaceNotOpenException if this device connection is not open. 951 * @throws NullPointerException if {@code address64Bit == null} or 952 * if {@code address16Bit == null} or 953 * if {@code data == null}. 954 * @throws XBeeException if there is any other XBee related exception. 955 * 956 * @see #sendExplicitData(RemoteXBeeDevice, int, int, int, int, byte[]) 957 * @see #sendExplicitData(XBee64BitAddress, int, int, int, int, byte[]) 958 * @see #sendExplicitData(XBee64BitAddress, XBee16BitAddress, int, int, int, int, byte[]) 959 * @see #sendExplicitDataAsync(RemoteXBeeDevice, int, int, int, int, byte[]) 960 * @see #sendExplicitDataAsync(XBee64BitAddress, int, int, int, int, byte[]) 961 * @see com.digi.xbee.api.models.XBee16BitAddress 962 * @see com.digi.xbee.api.models.XBee64BitAddress 963 */ 964 protected void sendExplicitDataAsync(XBee64BitAddress address64Bit, XBee16BitAddress address16Bit, int sourceEndpoint, 965 int destEndpoint, int clusterID, int profileID, byte[] data) throws XBeeException { 966 if (address64Bit == null) 967 throw new NullPointerException("64-bit address cannot be null."); 968 if (address16Bit == null) 969 throw new NullPointerException("16-bit address cannot be null."); 970 if (data == null) 971 throw new NullPointerException("Data cannot be null."); 972 if (sourceEndpoint < 0 || sourceEndpoint > 0xFF) 973 throw new IllegalArgumentException("Source endpoint must be between 0 and 0xFF."); 974 if (destEndpoint < 0 || destEndpoint > 0xFF) 975 throw new IllegalArgumentException("Destination endpoint must be between 0 and 0xFF."); 976 if (clusterID < 0 || clusterID > 0xFFFF) 977 throw new IllegalArgumentException("Cluster ID must be between 0 and 0xFFFF."); 978 if (profileID < 0 || profileID > 0xFFFF) 979 throw new IllegalArgumentException("Profile ID must be between 0 and 0xFFFF."); 980 981 // Check if device is remote. 982 if (isRemote()) 983 throw new OperationNotSupportedException("Cannot send explicit data to a remote device from a remote device."); 984 985 logger.debug(toString() + "Sending explicit data asynchronously to {}[{}] [{} - {} - {} - {}] >> {}.", address64Bit, address16Bit, 986 HexUtils.integerToHexString(sourceEndpoint, 1), HexUtils.integerToHexString(destEndpoint, 1), 987 HexUtils.integerToHexString(clusterID, 2), HexUtils.integerToHexString(profileID, 2), 988 HexUtils.prettyHexString(data)); 989 990 XBeePacket xbeePacket = new ExplicitAddressingPacket(getNextFrameID(), address64Bit, address16Bit, sourceEndpoint, destEndpoint, clusterID, profileID, 0, XBeeTransmitOptions.NONE, data); 991 sendAndCheckXBeePacket(xbeePacket, true); 992 } 993 994 /** 995 * Sends asynchronously the provided data in application layer mode to the 996 * provided XBee device choosing the optimal send method depending on the 997 * protocol of the local XBee device. Application layer mode means that you 998 * need to specify the application layer fields to be sent with the data. 999 * 1000 * <p>Asynchronous transmissions do not wait for answer from the remote 1001 * device or for transmit status packet.</p> 1002 * 1003 * @param remoteXBeeDevice The XBee device of the network that will receive 1004 * the data. 1005 * @param sourceEndpoint Source endpoint for the transmission. 1006 * @param destEndpoint Destination endpoint for the transmission. 1007 * @param clusterID Cluster ID used in the transmission. 1008 * @param profileID Profile ID used in the transmission. 1009 * @param data Byte array containing the data to be sent. 1010 * 1011 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 1012 * if {@code sourceEndpoint > 0xFF} or 1013 * if {@code destEndpoint < 0} or 1014 * if {@code destEndpoint > 0xFF} or 1015 * if {@code clusterID < 0} or 1016 * if {@code clusterID > 0xFFFF} or 1017 * if {@code profileID < 0} or 1018 * if {@code profileID > 0xFFFF}. 1019 * @throws InterfaceNotOpenException if this device connection is not open. 1020 * @throws NullPointerException if {@code remoteXBeeDevice == null} or 1021 * if {@code data == null}. 1022 * @throws XBeeException if there is any other XBee related exception. 1023 * 1024 * @see #sendExplicitData(RemoteXBeeDevice, int, int, int, int, byte[]) 1025 * @see #sendExplicitData(XBee64BitAddress, int, int, int, int, byte[]) 1026 * @see #sendExplicitData(XBee64BitAddress, XBee16BitAddress, int, int, int, int, byte[]) 1027 * @see #sendExplicitDataAsync(XBee64BitAddress, int, int, int, int, byte[]) 1028 * @see #sendExplicitDataAsync(XBee64BitAddress, XBee16BitAddress, int, int, int, int, byte[]) 1029 * @see RemoteXBeeDevice 1030 */ 1031 protected void sendExplicitDataAsync(RemoteXBeeDevice remoteXBeeDevice, int sourceEndpoint, int destEndpoint, 1032 int clusterID, int profileID, byte[] data) throws XBeeException { 1033 if (remoteXBeeDevice == null) 1034 throw new NullPointerException("Remote XBee device cannot be null"); 1035 1036 switch (getXBeeProtocol()) { 1037 case ZIGBEE: 1038 case DIGI_POINT: 1039 if (remoteXBeeDevice.get64BitAddress() != null && remoteXBeeDevice.get16BitAddress() != null) 1040 sendExplicitDataAsync(remoteXBeeDevice.get64BitAddress(), remoteXBeeDevice.get16BitAddress(), sourceEndpoint, destEndpoint, clusterID, profileID, data); 1041 else 1042 sendExplicitDataAsync(remoteXBeeDevice.get64BitAddress(), sourceEndpoint, destEndpoint, clusterID, profileID, data); 1043 break; 1044 case RAW_802_15_4: 1045 throw new OperationNotSupportedException("802.15.4. protocol does not support explicit data transmissions."); 1046 case DIGI_MESH: 1047 default: 1048 sendExplicitDataAsync(remoteXBeeDevice.get64BitAddress(), sourceEndpoint, destEndpoint, clusterID, profileID, data); 1049 } 1050 } 1051 1052 /** 1053 * Sends the provided data in application layer mode to the XBee device of 1054 * the network corresponding to the given 64-bit address. Application layer 1055 * mode means that you need to specify the application layer fields to be 1056 * sent with the data. 1057 * 1058 * <p>This method blocks till a success or error response arrives or the 1059 * configured receive timeout expires.</p> 1060 * 1061 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1062 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1063 * 1064 * @param address The 64-bit address of the XBee that will receive the data. 1065 * @param sourceEndpoint Source endpoint for the transmission. 1066 * @param destEndpoint Destination endpoint for the transmission. 1067 * @param clusterID Cluster ID used in the transmission. 1068 * @param profileID Profile ID used in the transmission. 1069 * @param data Byte array containing the data to be sent. 1070 * 1071 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 1072 * if {@code sourceEndpoint > 0xFF} or 1073 * if {@code destEndpoint < 0} or 1074 * if {@code destEndpoint > 0xFF} or 1075 * if {@code clusterID < 0} or 1076 * if {@code clusterID > 0xFFFF} or 1077 * if {@code profileID < 0} or 1078 * if {@code profileID > 0xFFFF}. 1079 * @throws InterfaceNotOpenException if this device connection is not open. 1080 * @throws NullPointerException if {@code address == null} or 1081 * if {@code data == null}. 1082 * @throws TimeoutException if there is a timeout sending the data. 1083 * @throws XBeeException if there is any other XBee related exception. 1084 * 1085 * @see #getReceiveTimeout() 1086 * @see #sendExplicitData(RemoteXBeeDevice, int, int, int, int, byte[]) 1087 * @see #sendExplicitData(XBee64BitAddress, XBee16BitAddress, int, int, int, int, byte[]) 1088 * @see #setReceiveTimeout(int) 1089 * @see com.digi.xbee.api.models.XBee64BitAddress 1090 */ 1091 protected void sendExplicitData(XBee64BitAddress address, int sourceEndpoint, int destEndpoint, int clusterID, 1092 int profileID, byte[] data) throws TimeoutException, XBeeException { 1093 if (address == null) 1094 throw new NullPointerException("Address cannot be null"); 1095 if (data == null) 1096 throw new NullPointerException("Data cannot be null."); 1097 if (sourceEndpoint < 0 || sourceEndpoint > 0xFF) 1098 throw new IllegalArgumentException("Source endpoint must be between 0 and 0xFF."); 1099 if (destEndpoint < 0 || destEndpoint > 0xFF) 1100 throw new IllegalArgumentException("Destination endpoint must be between 0 and 0xFF."); 1101 if (clusterID < 0 || clusterID > 0xFFFF) 1102 throw new IllegalArgumentException("Cluster ID must be between 0 and 0xFFFF."); 1103 if (profileID < 0 || profileID > 0xFFFF) 1104 throw new IllegalArgumentException("Profile ID must be between 0 and 0xFFFF."); 1105 1106 // Check if device is remote. 1107 if (isRemote()) 1108 throw new OperationNotSupportedException("Cannot send explicit data to a remote device from a remote device."); 1109 1110 logger.debug(toString() + "Sending explicit data to {} [{} - {} - {} - {}] >> {}.", address, HexUtils.integerToHexString(sourceEndpoint, 1), 1111 HexUtils.integerToHexString(destEndpoint, 1), HexUtils.integerToHexString(clusterID, 2), 1112 HexUtils.integerToHexString(profileID, 2), HexUtils.prettyHexString(data)); 1113 1114 XBeePacket xbeePacket = new ExplicitAddressingPacket(getNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, sourceEndpoint, destEndpoint, clusterID, profileID, 0, XBeeTransmitOptions.NONE, data); 1115 sendAndCheckXBeePacket(xbeePacket, false); 1116 } 1117 1118 /** 1119 * Sends the provided data in application layer mode to the XBee device of 1120 * the network corresponding to the given 64-bit/16-bit address. 1121 * Application layer mode means that you need to specify the application 1122 * layer fields to be sent with the data. 1123 * 1124 * <p>This method blocks till a success or error response arrives or the 1125 * configured receive timeout expires.</p> 1126 * 1127 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1128 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1129 * 1130 * @param address64Bit The 64-bit address of the XBee that will receive the 1131 * data. 1132 * @param address16Bit The 16-bit address of the XBee that will receive the 1133 * data. If it is unknown the 1134 * {@code XBee16BitAddress.UNKNOWN_ADDRESS} must be 1135 * used. 1136 * @param sourceEndpoint Source endpoint for the transmission. 1137 * @param destEndpoint Destination endpoint for the transmission. 1138 * @param clusterID Cluster ID used in the transmission. 1139 * @param profileID Profile ID used in the transmission. 1140 * @param data Byte array containing the data to be sent. 1141 * 1142 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 1143 * if {@code sourceEndpoint > 0xFF} or 1144 * if {@code destEndpoint < 0} or 1145 * if {@code destEndpoint > 0xFF} or 1146 * if {@code clusterID < 0} or 1147 * if {@code clusterID > 0xFFFF} or 1148 * if {@code profileID < 0} or 1149 * if {@code profileID > 0xFFFF}. 1150 * @throws InterfaceNotOpenException if this device connection is not open. 1151 * @throws NullPointerException if {@code address == null} or 1152 * if {@code data == null}. 1153 * @throws TimeoutException if there is a timeout sending the data. 1154 * @throws XBeeException if there is any other XBee related exception. 1155 * 1156 * @see #getReceiveTimeout() 1157 * @see #sendExplicitData(RemoteXBeeDevice, int, int, int, int, byte[]) 1158 * @see #sendExplicitData(XBee64BitAddress, int, int, int, int, byte[]) 1159 * @see #setReceiveTimeout(int) 1160 * @see com.digi.xbee.api.models.XBee16BitAddress 1161 * @see com.digi.xbee.api.models.XBee64BitAddress 1162 */ 1163 protected void sendExplicitData(XBee64BitAddress address64Bit, XBee16BitAddress address16Bit, int sourceEndpoint, int destEndpoint, 1164 int clusterID, int profileID, byte[] data) throws TimeoutException, XBeeException { 1165 // Verify the parameters are not null, if they are null, throw an exception. 1166 if (address64Bit == null) 1167 throw new NullPointerException("64-bit address cannot be null"); 1168 if (address16Bit == null) 1169 throw new NullPointerException("16-bit address cannot be null"); 1170 if (data == null) 1171 throw new NullPointerException("Data cannot be null."); 1172 if (sourceEndpoint < 0 || sourceEndpoint > 0xFF) 1173 throw new IllegalArgumentException("Source endpoint must be between 0 and 0xFF."); 1174 if (destEndpoint < 0 || destEndpoint > 0xFF) 1175 throw new IllegalArgumentException("Destination endpoint must be between 0 and 0xFF."); 1176 if (clusterID < 0 || clusterID > 0xFFFF) 1177 throw new IllegalArgumentException("Cluster ID must be between 0 and 0xFFFF."); 1178 if (profileID < 0 || profileID > 0xFFFF) 1179 throw new IllegalArgumentException("Profile ID must be between 0 and 0xFFFF."); 1180 1181 // Check if device is remote. 1182 if (isRemote()) 1183 throw new OperationNotSupportedException("Cannot send explicit data to a remote device from a remote device."); 1184 1185 logger.debug(toString() + "Sending explicit data to {}[{}] [{} - {} - {} - {}] >> {}.", address64Bit, address16Bit, 1186 HexUtils.integerToHexString(sourceEndpoint, 1), HexUtils.integerToHexString(destEndpoint, 1), 1187 HexUtils.integerToHexString(clusterID, 2), HexUtils.integerToHexString(profileID, 2), 1188 HexUtils.prettyHexString(data)); 1189 1190 XBeePacket xbeePacket = new ExplicitAddressingPacket(getNextFrameID(), address64Bit, address16Bit, sourceEndpoint, destEndpoint, clusterID, profileID, 0, XBeeTransmitOptions.NONE, data); 1191 sendAndCheckXBeePacket(xbeePacket, false); 1192 } 1193 1194 /** 1195 * Sends the provided data to the given XBee device in application layer 1196 * mode choosing the optimal send method depending on the protocol of the 1197 * local XBee device. Application layer mode means that you need to specify 1198 * the application layer fields to be sent with the data. 1199 * 1200 * <p>This method blocks till a success or error response arrives or the 1201 * configured receive timeout expires.</p> 1202 * 1203 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1204 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1205 * 1206 * @param remoteXBeeDevice The XBee device of the network that will receive 1207 * the explicit data. 1208 * @param sourceEndpoint Source endpoint for the transmission. 1209 * @param destEndpoint Destination endpoint for the transmission. 1210 * @param clusterID Cluster ID used in the transmission. 1211 * @param profileID Profile ID used in the transmission. 1212 * @param data Byte array containing the data to be sent. 1213 * 1214 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 1215 * if {@code sourceEndpoint > 0xFF} or 1216 * if {@code destEndpoint < 0} or 1217 * if {@code destEndpoint > 0xFF} or 1218 * if {@code clusterID < 0} or 1219 * if {@code clusterID > 0xFFFF} or 1220 * if {@code profileID < 0} or 1221 * if {@code profileID > 0xFFFF}. 1222 * @throws InterfaceNotOpenException if this device connection is not open. 1223 * @throws NullPointerException if {@code remoteXBeeDevice == null} or 1224 * if {@code data == null}. 1225 * @throws TimeoutException if there is a timeout sending the data. 1226 * @throws XBeeException if there is any other XBee related exception. 1227 * 1228 * @see #getReceiveTimeout() 1229 * @see #sendExplicitData(XBee64BitAddress, int, int, int, int, byte[]) 1230 * @see #sendExplicitData(XBee64BitAddress, XBee16BitAddress, int, int, int, int, byte[]) 1231 * @see #setReceiveTimeout(int) 1232 * @see com.digi.xbee.api.RemoteXBeeDevice 1233 */ 1234 protected void sendExplicitData(RemoteXBeeDevice remoteXBeeDevice, int sourceEndpoint, int destEndpoint, int clusterID, 1235 int profileID, byte[] data) throws TimeoutException, XBeeException { 1236 if (remoteXBeeDevice == null) 1237 throw new NullPointerException("Remote XBee device cannot be null."); 1238 1239 switch (getXBeeProtocol()) { 1240 case ZIGBEE: 1241 case DIGI_POINT: 1242 if (remoteXBeeDevice.get64BitAddress() != null && remoteXBeeDevice.get16BitAddress() != null) 1243 sendExplicitData(remoteXBeeDevice.get64BitAddress(), remoteXBeeDevice.get16BitAddress(), sourceEndpoint, destEndpoint, clusterID, profileID, data); 1244 else 1245 sendExplicitData(remoteXBeeDevice.get64BitAddress(), sourceEndpoint, destEndpoint, clusterID, profileID, data); 1246 break; 1247 case RAW_802_15_4: 1248 throw new OperationNotSupportedException("802.15.4. protocol does not support explicit data transmissions."); 1249 case DIGI_MESH: 1250 default: 1251 sendExplicitData(remoteXBeeDevice.get64BitAddress(), sourceEndpoint, destEndpoint, clusterID, profileID, data); 1252 } 1253 } 1254 1255 /** 1256 * Sends the provided data to all the XBee nodes of the network (broadcast) 1257 * in application layer mode. Application layer mode means that you need to 1258 * specify the application layer fields to be sent with the data. 1259 * 1260 * <p>This method blocks till a success or error transmit status arrives or 1261 * the configured receive timeout expires.</p> 1262 * 1263 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1264 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1265 * 1266 * @param sourceEndpoint Source endpoint for the transmission. 1267 * @param destEndpoint Destination endpoint for the transmission. 1268 * @param clusterID Cluster ID used in the transmission. 1269 * @param profileID Profile ID used in the transmission. 1270 * @param data Byte array containing the data to be sent. 1271 * 1272 * @throws IllegalArgumentException if {@code sourceEndpoint < 0} or 1273 * if {@code sourceEndpoint > 0xFF} or 1274 * if {@code destEndpoint < 0} or 1275 * if {@code destEndpoint > 0xFF} or 1276 * if {@code clusterID < 0} or 1277 * if {@code clusterID > 0xFFFF} or 1278 * if {@code profileID < 0} or 1279 * if {@code profileID > 0xFFFF}. 1280 * @throws InterfaceNotOpenException if this device connection is not open. 1281 * @throws NullPointerException if {@code remoteXBeeDevice == null} or 1282 * if {@code data == null}. 1283 * @throws TimeoutException if there is a timeout sending the data. 1284 * @throws XBeeException if there is any other XBee related exception. 1285 * 1286 * @see #getReceiveTimeout() 1287 * @see #setReceiveTimeout(int) 1288 */ 1289 protected void sendBroadcastExplicitData(int sourceEndpoint, int destEndpoint, int clusterID, int profileID, 1290 byte[] data) throws TimeoutException, XBeeException { 1291 if (getXBeeProtocol() == XBeeProtocol.RAW_802_15_4) 1292 throw new OperationNotSupportedException("802.15.4. protocol does not support explicit data transmissions."); 1293 sendExplicitData(XBee64BitAddress.BROADCAST_ADDRESS, sourceEndpoint, destEndpoint, clusterID, profileID, data); 1294 } 1295 1296 /** 1297 * Sends the given XBee packet and registers the given packet listener 1298 * (if not {@code null}) to be notified when the answers is received. 1299 * 1300 * <p>This is a non-blocking operation. To wait for the answer use 1301 * {@code sendPacket(XBeePacket)}.</p> 1302 * 1303 * @param packet XBee packet to be sent. 1304 * @param packetReceiveListener Listener for the operation, {@code null} 1305 * not to be notified when the answer arrives. 1306 * 1307 * @throws InterfaceNotOpenException if this device connection is not open. 1308 * @throws NullPointerException if {@code packet == null}. 1309 * @throws XBeeException if there is any other XBee related exception. 1310 * 1311 * @see #sendPacket(XBeePacket) 1312 * @see #sendPacketAsync(XBeePacket) 1313 * @see com.digi.xbee.api.listeners.IPacketReceiveListener 1314 * @see com.digi.xbee.api.packet.XBeePacket 1315 */ 1316 public void sendPacket(XBeePacket packet, IPacketReceiveListener packetReceiveListener) throws XBeeException { 1317 try { 1318 sendXBeePacket(packet, packetReceiveListener); 1319 } catch (IOException e) { 1320 throw new XBeeException("Error writing in the communication interface.", e); 1321 } 1322 } 1323 1324 /** 1325 * Sends the given XBee packet asynchronously. 1326 * 1327 * <p>This is a non-blocking operation that do not wait for the answer and 1328 * is never notified when it arrives.</p> 1329 * 1330 * <p>To be notified when the answer is received, use 1331 * {@link #sendXBeePacket(XBeePacket, IPacketReceiveListener)}.</p> 1332 * 1333 * @param packet XBee packet to be sent asynchronously. 1334 * 1335 * @throws InterfaceNotOpenException if this device connection is not open. 1336 * @throws NullPointerException if {@code packet == null}. 1337 * @throws XBeeException if there is any other XBee related exception. 1338 * 1339 * @see #sendXBeePacket(XBeePacket) 1340 * @see #sendXBeePacket(XBeePacket, IPacketReceiveListener) 1341 * @see com.digi.xbee.api.packet.XBeePacket 1342 */ 1343 public void sendPacketAsync(XBeePacket packet) throws XBeeException { 1344 try { 1345 super.sendXBeePacket(packet, null); 1346 } catch (IOException e) { 1347 throw new XBeeException("Error writing in the communication interface.", e); 1348 } 1349 } 1350 1351 /** 1352 * Sends the given XBee packet synchronously and blocks until the response 1353 * is received or the configured receive timeout expires. 1354 * 1355 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1356 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1357 * 1358 * <p>Use {@code sendXBeePacketAsync(XBeePacket)} or 1359 * {@code #sendXBeePacket(XBeePacket, IPacketReceiveListener)} for 1360 * non-blocking operations.</p> 1361 * 1362 * @param packet XBee packet to be sent. 1363 * 1364 * @return An {@code XBeePacket} object containing the response of the sent 1365 * packet or {@code null} if there is no response. 1366 * 1367 * @throws InterfaceNotOpenException if this device connection is not open. 1368 * @throws NullPointerException if {@code packet == null}. 1369 * @throws TimeoutException if there is a timeout sending the XBee packet. 1370 * @throws XBeeException if there is any other XBee related exception. 1371 * 1372 * @see #getReceiveTimeout() 1373 * @see #sendXBeePacket(XBeePacket, IPacketReceiveListener) 1374 * @see #sendXBeePacketAsync(XBeePacket) 1375 * @see #setReceiveTimeout(int) 1376 * @see com.digi.xbee.api.packet.XBeePacket 1377 */ 1378 public XBeePacket sendPacket(XBeePacket packet) throws TimeoutException, XBeeException { 1379 try { 1380 return super.sendXBeePacket(packet); 1381 } catch (IOException e) { 1382 throw new XBeeException("Error writing in the communication interface.", e); 1383 } 1384 } 1385 1386 /** 1387 * Waits until a Modem Status packet with a reset status, 1388 * {@code ModemStatusEvent.STATUS_HARDWARE_RESET} (0x00), or a watchdog 1389 * timer reset, {@code ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET} (0x01), 1390 * is received or the timeout expires. 1391 * 1392 * @return {@code true} if the Modem Status packet is received, 1393 * {@code false} otherwise. 1394 * 1395 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_HARDWARE_RESET 1396 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_WATCHDOG_TIMER_RESET 1397 */ 1398 private boolean waitForModemResetStatusPacket() { 1399 modemStatusReceived = false; 1400 addModemStatusListener(resetStatusListener); 1401 synchronized (resetLock) { 1402 try { 1403 resetLock.wait(TIMEOUT_RESET); 1404 } catch (InterruptedException e) { } 1405 } 1406 removeModemStatusListener(resetStatusListener); 1407 return modemStatusReceived; 1408 } 1409 1410 /** 1411 * Custom listener for modem reset packets. 1412 * 1413 * <p>When a Modem Status packet is received with status 1414 * {@code ModemStatusEvent.STATUS_HARDWARE_RESET} or 1415 * {@code ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET}, it 1416 * notifies the object that was waiting for the reception.</p> 1417 * 1418 * @see com.digi.xbee.api.listeners.IModemStatusReceiveListener 1419 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_HARDWARE_RESET 1420 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_WATCHDOG_TIMER_RESET 1421 */ 1422 private IModemStatusReceiveListener resetStatusListener = new IModemStatusReceiveListener() { 1423 1424 /* 1425 * (non-Javadoc) 1426 * @see com.digi.xbee.api.listeners.IModemStatusReceiveListener#modemStatusEventReceived(com.digi.xbee.api.models.ModemStatusEvent) 1427 */ 1428 @Override 1429 public void modemStatusEventReceived(ModemStatusEvent modemStatusEvent) { 1430 if (modemStatusEvent == ModemStatusEvent.STATUS_HARDWARE_RESET 1431 || modemStatusEvent == ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET){ 1432 modemStatusReceived = true; 1433 // Continue execution by notifying the lock object. 1434 synchronized (resetLock) { 1435 resetLock.notify(); 1436 } 1437 } 1438 } 1439 }; 1440 1441 /* 1442 * (non-Javadoc) 1443 * @see com.digi.xbee.api.AbstractXBeeDevice#reset() 1444 */ 1445 @Override 1446 public void reset() throws TimeoutException, XBeeException { 1447 // Check connection. 1448 if (!connectionInterface.isOpen()) 1449 throw new InterfaceNotOpenException(); 1450 1451 logger.info(toString() + "Resetting the local module..."); 1452 1453 ATCommandResponse response = null; 1454 try { 1455 response = sendATCommand(new ATCommand("FR")); 1456 } catch (IOException e) { 1457 throw new XBeeException("Error writing in the communication interface.", e); 1458 } 1459 1460 // Check if AT Command response is valid. 1461 checkATCommandResponseIsValid(response); 1462 1463 // Wait for a Modem Status packet. 1464 if (!waitForModemResetStatusPacket()) 1465 throw new TimeoutException("Timeout waiting for the Modem Status packet."); 1466 1467 logger.info(toString() + "Module reset successfully."); 1468 } 1469 1470 /** 1471 * Reads new data received by this XBee device during the configured 1472 * receive timeout. 1473 * 1474 * <p>This method blocks until new data is received or the configured 1475 * receive timeout expires.</p> 1476 * 1477 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1478 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1479 * 1480 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1481 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1482 * 1483 * @return An {@code XBeeMessage} object containing the data and the source 1484 * address of the remote node that sent the data. {@code null} if 1485 * this did not receive new data during the configured receive 1486 * timeout. 1487 * 1488 * @throws InterfaceNotOpenException if this device connection is not open. 1489 * 1490 * @see #readData(int) 1491 * @see #getReceiveTimeout() 1492 * @see #setReceiveTimeout(int) 1493 * @see #readDataFrom(RemoteXBeeDevice) 1494 * @see #readDataFrom(RemoteXBeeDevice, int) 1495 * @see com.digi.xbee.api.models.XBeeMessage 1496 */ 1497 public XBeeMessage readData() { 1498 return readDataPacket(null, TIMEOUT_READ_PACKET); 1499 } 1500 1501 /** 1502 * Reads new data received by this XBee device during the provided timeout. 1503 * 1504 * <p>This method blocks until new data is received or the provided timeout 1505 * expires.</p> 1506 * 1507 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1508 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1509 * 1510 * @param timeout The time to wait for new data in milliseconds. 1511 * 1512 * @return An {@code XBeeMessage} object containing the data and the source 1513 * address of the remote node that sent the data. {@code null} if 1514 * this device did not receive new data during {@code timeout} 1515 * milliseconds. 1516 * 1517 * @throws IllegalArgumentException if {@code timeout < 0}. 1518 * @throws InterfaceNotOpenException if this device connection is not open. 1519 * 1520 * @see #readData() 1521 * @see #readDataFrom(RemoteXBeeDevice) 1522 * @see #readDataFrom(RemoteXBeeDevice, int) 1523 * @see com.digi.xbee.api.models.XBeeMessage 1524 */ 1525 public XBeeMessage readData(int timeout) { 1526 if (timeout < 0) 1527 throw new IllegalArgumentException("Read timeout must be 0 or greater."); 1528 1529 return readDataPacket(null, timeout); 1530 } 1531 1532 /** 1533 * Reads new data received from the given remote XBee device during the 1534 * configured receive timeout. 1535 * 1536 * <p>This method blocks until new data from the provided remote XBee 1537 * device is received or the configured receive timeout expires.</p> 1538 * 1539 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1540 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1541 * 1542 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1543 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1544 * 1545 * @param remoteXBeeDevice The remote device to read data from. 1546 * 1547 * @return An {@code XBeeMessage} object containing the data and the source 1548 * address of the remote node that sent the data. {@code null} if 1549 * this device did not receive new data from the provided remote 1550 * XBee device during the configured receive timeout. 1551 * 1552 * @throws InterfaceNotOpenException if this device connection is not open. 1553 * @throws NullPointerException if {@code remoteXBeeDevice == null}. 1554 * 1555 * @see #readDataFrom(RemoteXBeeDevice, int) 1556 * @see #getReceiveTimeout() 1557 * @see #setReceiveTimeout(int) 1558 * @see #readData() 1559 * @see #readData(int) 1560 * @see RemoteXBeeDevice 1561 * @see com.digi.xbee.api.models.XBeeMessage 1562 */ 1563 public XBeeMessage readDataFrom(RemoteXBeeDevice remoteXBeeDevice) { 1564 if (remoteXBeeDevice == null) 1565 throw new NullPointerException("Remote XBee device cannot be null."); 1566 1567 return readDataPacket(remoteXBeeDevice, TIMEOUT_READ_PACKET); 1568 } 1569 1570 /** 1571 * Reads new data received from the given remote XBee device during the 1572 * provided timeout. 1573 * 1574 * <p>This method blocks until new data from the provided remote XBee 1575 * device is received or the given timeout expires.</p> 1576 * 1577 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1578 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1579 * 1580 * @param remoteXBeeDevice The remote device to read data from. 1581 * @param timeout The time to wait for new data in milliseconds. 1582 * 1583 * @return An {@code XBeeMessage} object containing the data and the source 1584 * address of the remote node that sent the data. {@code null} if 1585 * this device did not receive new data from the provided remote 1586 * XBee device during {@code timeout} milliseconds. 1587 * 1588 * @throws IllegalArgumentException if {@code timeout < 0}. 1589 * @throws InterfaceNotOpenException if this device connection is not open. 1590 * @throws NullPointerException if {@code remoteXBeeDevice == null}. 1591 * 1592 * @see #readDataFrom(RemoteXBeeDevice) 1593 * @see #getReceiveTimeout() 1594 * @see #setReceiveTimeout(int) 1595 * @see #readData() 1596 * @see #readData(int) 1597 * @see RemoteXBeeDevice 1598 * @see com.digi.xbee.api.models.XBeeMessage 1599 */ 1600 public XBeeMessage readDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) { 1601 if (remoteXBeeDevice == null) 1602 throw new NullPointerException("Remote XBee device cannot be null."); 1603 if (timeout < 0) 1604 throw new IllegalArgumentException("Read timeout must be 0 or greater."); 1605 1606 return readDataPacket(remoteXBeeDevice, timeout); 1607 } 1608 1609 /** 1610 * Reads a new data packet received by this XBee device during the provided 1611 * timeout. 1612 * 1613 * <p>This method blocks until new data is received or the given timeout 1614 * expires.</p> 1615 * 1616 * <p>If the provided remote XBee device is {@code null} the method returns 1617 * the first data packet read from any remote device. 1618 * <br> 1619 * If the remote device is not {@code null} the method returns the first 1620 * data package read from the provided device. 1621 * </p> 1622 * 1623 * @param remoteXBeeDevice The remote device to get a data packet from. 1624 * {@code null} to read a data packet sent by any 1625 * remote XBee device. 1626 * @param timeout The time to wait for a data packet in milliseconds. 1627 * 1628 * @return An {@code XBeeMessage} received by this device, containing the 1629 * data and the source address of the remote node that sent the 1630 * data. {@code null} if this device did not receive new data 1631 * during {@code timeout} milliseconds, or if any error occurs while 1632 * trying to get the source of the message. 1633 * 1634 * @throws InterfaceNotOpenException if this device connection is not open. 1635 * 1636 * @see RemoteXBeeDevice 1637 * @see com.digi.xbee.api.models.XBeeMessage 1638 */ 1639 private XBeeMessage readDataPacket(RemoteXBeeDevice remoteXBeeDevice, int timeout) { 1640 // Check connection. 1641 if (!connectionInterface.isOpen()) 1642 throw new InterfaceNotOpenException(); 1643 1644 XBeePacketsQueue xbeePacketsQueue = dataReader.getXBeePacketsQueue(); 1645 XBeePacket xbeePacket = null; 1646 1647 if (remoteXBeeDevice != null) 1648 xbeePacket = xbeePacketsQueue.getFirstDataPacketFrom(remoteXBeeDevice, timeout); 1649 else 1650 xbeePacket = xbeePacketsQueue.getFirstDataPacket(timeout); 1651 1652 if (xbeePacket == null) 1653 return null; 1654 1655 // Obtain the remote device from the packet. 1656 RemoteXBeeDevice remoteDevice = null; 1657 try { 1658 remoteDevice = dataReader.getRemoteXBeeDeviceFromPacket((XBeeAPIPacket)xbeePacket); 1659 // If the provided device is not null, add it to the network, so the 1660 // device provided is the one that will remain in the network. 1661 if (remoteXBeeDevice != null) 1662 remoteDevice = getNetwork().addRemoteDevice(remoteXBeeDevice); 1663 1664 // The packet always contains information of the source so the 1665 // remote device should never be null. 1666 if (remoteDevice == null) 1667 return null; 1668 1669 } catch (XBeeException e) { 1670 logger.error(e.getMessage(), e); 1671 return null; 1672 } 1673 1674 // Obtain the data from the packet. 1675 byte[] data = null; 1676 1677 switch (((XBeeAPIPacket)xbeePacket).getFrameType()) { 1678 case RECEIVE_PACKET: 1679 ReceivePacket receivePacket = (ReceivePacket)xbeePacket; 1680 data = receivePacket.getRFData(); 1681 break; 1682 case RX_16: 1683 RX16Packet rx16Packet = (RX16Packet)xbeePacket; 1684 data = rx16Packet.getRFData(); 1685 break; 1686 case RX_64: 1687 RX64Packet rx64Packet = (RX64Packet)xbeePacket; 1688 data = rx64Packet.getRFData(); 1689 break; 1690 default: 1691 return null; 1692 } 1693 1694 // Create and return the XBee message. 1695 return new XBeeMessage(remoteDevice, data, ((XBeeAPIPacket)xbeePacket).isBroadcast()); 1696 } 1697 1698 /** 1699 * Reads new explicit data received by this XBee device during the 1700 * configured receive timeout. 1701 * 1702 * <p>This method blocks until new explicit data is received or the 1703 * configured receive timeout expires.</p> 1704 * 1705 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1706 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1707 * 1708 * <p>For non-blocking operations, register a 1709 * {@code IExplicitDataReceiveListener} using the method 1710 * {@link #addExplicitDataListener(IExplicitDataReceiveListener)}.</p> 1711 * 1712 * @return An {@code ExplicitXBeeMessage} object containing the explicit 1713 * data, the source address of the remote node that sent the data 1714 * and other values related to the transmission. {@code null} if 1715 * this did not receive new explicit data during the configured 1716 * receive timeout. 1717 * 1718 * @throws InterfaceNotOpenException if this device connection is not open. 1719 * 1720 * @see #getReceiveTimeout() 1721 * @see #readExplicitData(int) 1722 * @see #readExplicitDataFrom(RemoteXBeeDevice) 1723 * @see #readExplicitDataFrom(RemoteXBeeDevice, int) 1724 * @see #setReceiveTimeout(int) 1725 * @see com.digi.xbee.api.models.ExplicitXBeeMessage 1726 */ 1727 protected ExplicitXBeeMessage readExplicitData() { 1728 return readExplicitDataPacket(null, TIMEOUT_READ_PACKET); 1729 } 1730 1731 /** 1732 * Reads new explicit data received by this XBee device during the provided 1733 * timeout. 1734 * 1735 * <p>This method blocks until new explicit data is received or the 1736 * provided timeout expires.</p> 1737 * 1738 * <p>For non-blocking operations, register a 1739 * {@code IExplicitDataReceiveListener} using the method 1740 * {@link #addExplicitDataListener(IExplicitDataReceiveListener)}.</p> 1741 * 1742 * @param timeout The time to wait for new explicit data in milliseconds. 1743 * 1744 * @return An {@code ExplicitXBeeMessage} object containing the explicit 1745 * data, the source address of the remote node that sent the data 1746 * and other values related to the transmission. {@code null} if 1747 * this device did not receive new explicit data during 1748 * {@code timeout} milliseconds. 1749 * 1750 * @throws IllegalArgumentException if {@code timeout < 0}. 1751 * @throws InterfaceNotOpenException if this device connection is not open. 1752 * 1753 * @see #readExplicitData() 1754 * @see #readExplicitDataFrom(RemoteXBeeDevice) 1755 * @see #readExplicitDataFrom(RemoteXBeeDevice, int) 1756 * @see com.digi.xbee.api.models.ExplicitXBeeMessage 1757 */ 1758 protected ExplicitXBeeMessage readExplicitData(int timeout) { 1759 if (timeout < 0) 1760 throw new IllegalArgumentException("Read timeout must be 0 or greater."); 1761 1762 return readExplicitDataPacket(null, timeout); 1763 } 1764 1765 /** 1766 * Reads new explicit data received from the given remote XBee device 1767 * during the configured receive timeout. 1768 * 1769 * <p>This method blocks until new explicit data from the provided remote 1770 * XBee device is received or the configured receive timeout expires.</p> 1771 * 1772 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 1773 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1774 * 1775 * <p>For non-blocking operations, register a 1776 * {@code IExplicitDataReceiveListener} using the method 1777 * {@link #addExplicitDataListener(IExplicitDataReceiveListener)}.</p> 1778 * 1779 * @param remoteXBeeDevice The remote device to read explicit data from. 1780 * 1781 * @return An {@code ExplicitXBeeMessage} object containing the explicit 1782 * data, the source address of the remote node that sent the data 1783 * and other values related to the transmission. {@code null} if 1784 * this device did not receive new explicit data from the provided 1785 * remote XBee device during the configured receive timeout. 1786 * 1787 * @throws InterfaceNotOpenException if this device connection is not open. 1788 * @throws NullPointerException if {@code remoteXBeeDevice == null}. 1789 * 1790 * @see #getReceiveTimeout() 1791 * @see #readExplicitData() 1792 * @see #readExplicitData(int) 1793 * @see #readExplicitDataFrom(RemoteXBeeDevice, int) 1794 * @see #setReceiveTimeout(int) 1795 * @see RemoteXBeeDevice 1796 * @see com.digi.xbee.api.models.ExplicitXBeeMessage 1797 */ 1798 protected ExplicitXBeeMessage readExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice) { 1799 if (remoteXBeeDevice == null) 1800 throw new NullPointerException("Remote XBee device cannot be null."); 1801 1802 return readExplicitDataPacket(remoteXBeeDevice, TIMEOUT_READ_PACKET); 1803 } 1804 1805 /** 1806 * Reads new explicit data received from the given remote XBee device 1807 * during the provided timeout. 1808 * 1809 * <p>This method blocks until new explicit data from the provided remote 1810 * XBee device is received or the given timeout expires.</p> 1811 * 1812 * <p>For non-blocking operations, register a 1813 * {@code IExplicitDataReceiveListener} using the method 1814 * {@link #addExplicitDataListener(IExplicitDataReceiveListener)}.</p> 1815 * 1816 * @param remoteXBeeDevice The remote device to read explicit data from. 1817 * @param timeout The time to wait for new explicit data in milliseconds. 1818 * 1819 * @return An {@code ExplicitXBeeMessage} object containing the explicit 1820 * data, the source address of the remote node that sent the data 1821 * and other values related to the transmission. {@code null} if 1822 * this device did not receive new data from the provided remote 1823 * XBee device during {@code timeout} milliseconds. 1824 * 1825 * @throws IllegalArgumentException if {@code timeout < 0}. 1826 * @throws InterfaceNotOpenException if this device connection is not open. 1827 * @throws NullPointerException if {@code remoteXBeeDevice == null}. 1828 * 1829 * @see #getReceiveTimeout() 1830 * @see #readExplicitData() 1831 * @see #readExplicitData(int) 1832 * @see #readExplicitDataFrom(RemoteXBeeDevice) 1833 * @see #setReceiveTimeout(int) 1834 * @see RemoteXBeeDevice 1835 * @see com.digi.xbee.api.models.ExplicitXBeeMessage 1836 */ 1837 protected ExplicitXBeeMessage readExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) { 1838 if (remoteXBeeDevice == null) 1839 throw new NullPointerException("Remote XBee device cannot be null."); 1840 if (timeout < 0) 1841 throw new IllegalArgumentException("Read timeout must be 0 or greater."); 1842 1843 return readExplicitDataPacket(remoteXBeeDevice, timeout); 1844 } 1845 1846 /** 1847 * Reads a new explicit data packet received by this XBee device during 1848 * the provided timeout. 1849 * 1850 * <p>This method blocks until new explicit data is received or the given 1851 * timeout expires.</p> 1852 * 1853 * <p>If the provided remote XBee device is {@code null} the method returns 1854 * the first explicit data packet read from any remote device. 1855 * <br> 1856 * If the remote device is not {@code null} the method returns the first 1857 * explicit data package read from the provided device. 1858 * </p> 1859 * 1860 * @param remoteXBeeDevice The remote device to get an explicit data 1861 * packet from. {@code null} to read an explicit 1862 * data packet sent by any remote XBee device. 1863 * @param timeout The time to wait for an explicit data packet in 1864 * milliseconds. 1865 * 1866 * @return An {@code XBeeMessage} received by this device, containing the 1867 * explicit data and the source address of the remote node that 1868 * sent the data. {@code null} if this device did not receive new 1869 * explicit data during {@code timeout} milliseconds. 1870 * 1871 * @throws InterfaceNotOpenException if this device connection is not open. 1872 * 1873 * @see RemoteXBeeDevice 1874 * @see com.digi.xbee.api.models.ExplicitXBeeMessage 1875 */ 1876 private ExplicitXBeeMessage readExplicitDataPacket(RemoteXBeeDevice remoteXBeeDevice, int timeout) { 1877 // Check connection. 1878 if (!connectionInterface.isOpen()) 1879 throw new InterfaceNotOpenException(); 1880 1881 XBeePacketsQueue xbeePacketsQueue = dataReader.getXBeePacketsQueue(); 1882 XBeePacket xbeePacket = null; 1883 1884 if (remoteXBeeDevice != null) 1885 xbeePacket = xbeePacketsQueue.getFirstExplicitDataPacketFrom(remoteXBeeDevice, timeout); 1886 else 1887 xbeePacket = xbeePacketsQueue.getFirstExplicitDataPacket(timeout); 1888 1889 if (xbeePacket == null) 1890 return null; 1891 1892 // Verify the packet is an explicit data packet. 1893 APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType(); 1894 if (packetType != APIFrameType.EXPLICIT_RX_INDICATOR) 1895 return null; 1896 1897 // Obtain the necessary data from the packet. 1898 ExplicitRxIndicatorPacket explicitDataPacket = (ExplicitRxIndicatorPacket)xbeePacket; 1899 RemoteXBeeDevice remoteDevice = getNetwork().getDevice(explicitDataPacket.get64BitSourceAddress()); 1900 if (remoteDevice == null) { 1901 if (remoteXBeeDevice != null) 1902 remoteDevice = remoteXBeeDevice; 1903 else 1904 remoteDevice = new RemoteXBeeDevice(this, explicitDataPacket.get64BitSourceAddress()); 1905 getNetwork().addRemoteDevice(remoteDevice); 1906 } 1907 int sourceEndpoint = explicitDataPacket.getSourceEndpoint(); 1908 int destEndpoint = explicitDataPacket.getDestinationEndpoint(); 1909 int clusterID = explicitDataPacket.getClusterID(); 1910 int profileID = explicitDataPacket.getProfileID(); 1911 byte[] data = explicitDataPacket.getRFData(); 1912 1913 // Create and return the XBee message. 1914 return new ExplicitXBeeMessage(remoteDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data, ((XBeeAPIPacket)xbeePacket).isBroadcast()); 1915 } 1916 1917 /** 1918 * Configures the API output mode of the XBee device. 1919 * 1920 * <p>The API output mode determines the format that the received data is 1921 * output through the serial interface of the XBee device.</p> 1922 * 1923 * @param apiOutputMode The API output mode to be set to the XBee device. 1924 * 1925 * @throws InterfaceNotOpenException if this device connection is not open. 1926 * @throws NullPointerException if {@code apiOutputMode == null}. 1927 * @throws TimeoutException if there is a timeout configuring the API 1928 * output mode. 1929 * @throws XBeeException if there is any other XBee related exception. 1930 * 1931 * @see #getAPIOutputMode() 1932 * @see APIOutputMode 1933 */ 1934 protected void setAPIOutputMode(APIOutputMode apiOutputMode) throws TimeoutException, XBeeException { 1935 if (apiOutputMode == null) 1936 throw new NullPointerException("API output mode cannot be null."); 1937 1938 setParameter("AO", new byte[]{(byte)apiOutputMode.getValue()}); 1939 } 1940 1941 /** 1942 * Returns the API output mode of the XBee device. 1943 * 1944 * <p>The API output mode determines the format that the received data is 1945 * output through the serial interface of the XBee device.</p> 1946 * 1947 * @return The API output mode that the XBee device is configured with. 1948 * 1949 * @throws InterfaceNotOpenException if this device connection is not open. 1950 * @throws TimeoutException if there is a timeout getting the API output 1951 * mode from the device. 1952 * @throws XBeeException if there is any other XBee related exception. 1953 * 1954 * @see #setAPIOutputMode(APIOutputMode) 1955 * @see APIOutputMode 1956 */ 1957 protected APIOutputMode getAPIOutputMode() throws TimeoutException, XBeeException { 1958 byte[] apiOutputModeValue = getParameter("AO"); 1959 1960 return APIOutputMode.get(apiOutputModeValue[0]); 1961 } 1962 1963 /* 1964 * (non-Javadoc) 1965 * @see com.digi.xbee.api.AbstractXBeeDevice#toString() 1966 */ 1967 @Override 1968 public String toString() { 1969 String id = getNodeID() == null ? "" : getNodeID(); 1970 String addr64 = get64BitAddress() == null || get64BitAddress() == XBee64BitAddress.UNKNOWN_ADDRESS ? 1971 "" : get64BitAddress().toString(); 1972 1973 if (id.length() == 0 && addr64.length() == 0) 1974 return super.toString(); 1975 1976 StringBuilder message = new StringBuilder(super.toString()); 1977 message.append(addr64); 1978 if (id.length() > 0) { 1979 message.append(" ("); 1980 message.append(id); 1981 message.append(")"); 1982 } 1983 message.append(" - "); 1984 1985 return message.toString(); 1986 } 1987}