001/** 002 * Copyright (c) 2014 Digi International Inc., 003 * All rights not expressly granted are reserved. 004 * 005 * This Source Code Form is subject to the terms of the Mozilla Public 006 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 007 * You can obtain one at http://mozilla.org/MPL/2.0/. 008 * 009 * Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343 010 * ======================================================================= 011 */ 012package com.digi.xbee.api; 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.InterfaceAlreadyOpenException; 020import com.digi.xbee.api.exceptions.InterfaceNotOpenException; 021import com.digi.xbee.api.exceptions.InvalidOperatingModeException; 022import com.digi.xbee.api.exceptions.OperationNotSupportedException; 023import com.digi.xbee.api.exceptions.TimeoutException; 024import com.digi.xbee.api.exceptions.XBeeException; 025import com.digi.xbee.api.listeners.IIOSampleReceiveListener; 026import com.digi.xbee.api.listeners.IModemStatusReceiveListener; 027import com.digi.xbee.api.listeners.IPacketReceiveListener; 028import com.digi.xbee.api.listeners.IDataReceiveListener; 029import com.digi.xbee.api.models.ATCommand; 030import com.digi.xbee.api.models.ATCommandResponse; 031import com.digi.xbee.api.models.ModemStatusEvent; 032import com.digi.xbee.api.models.OperatingMode; 033import com.digi.xbee.api.models.XBee16BitAddress; 034import com.digi.xbee.api.models.XBee64BitAddress; 035import com.digi.xbee.api.models.XBeeMessage; 036import com.digi.xbee.api.models.XBeePacketsQueue; 037import com.digi.xbee.api.models.XBeeTransmitOptions; 038import com.digi.xbee.api.packet.APIFrameType; 039import com.digi.xbee.api.packet.XBeeAPIPacket; 040import com.digi.xbee.api.packet.XBeePacket; 041import com.digi.xbee.api.packet.common.ReceivePacket; 042import com.digi.xbee.api.packet.common.TransmitPacket; 043import com.digi.xbee.api.packet.raw.RX16Packet; 044import com.digi.xbee.api.packet.raw.RX64Packet; 045import com.digi.xbee.api.packet.raw.TX64Packet; 046import com.digi.xbee.api.utils.HexUtils; 047 048/** 049 * This class represents a local XBee device. 050 * 051 * @see DigiMeshDevice 052 * @see DigiPointDevice 053 * @see Raw802Device 054 * @see ZigBeeDevice 055 */ 056public class XBeeDevice extends AbstractXBeeDevice { 057 058 // Constants. 059 private static int TIMEOUT_RESET = 5000; 060 private static int TIMEOUT_READ_PACKET = 3000; 061 062 private static String COMMAND_MODE_CHAR = "+"; 063 private static String COMMAND_MODE_OK = "OK\r"; 064 065 // Variables. 066 protected XBeeNetwork network; 067 068 private Object resetLock = new Object(); 069 070 private boolean modemStatusReceived = false; 071 072 /** 073 * Class constructor. Instantiates a new {@code XBeeDevice} object 074 * physically connected to the given port name and configured at the 075 * provided baud rate. 076 * 077 * @param port Serial port name where XBee device is attached to. 078 * @param baudRate Serial port baud rate to communicate with the device. 079 * Other connection parameters will be set as default (8 080 * data bits, 1 stop bit, no parity, no flow control). 081 * 082 * @throws IllegalArgumentException if {@code baudRate < 0}. 083 * @throws NullPointerException if {@code port == null}. 084 * 085 * @see #XBeeDevice(IConnectionInterface) 086 * @see #XBeeDevice(String, SerialPortParameters) 087 * @see #XBeeDevice(String, int, int, int, int, int) 088 */ 089 public XBeeDevice(String port, int baudRate) { 090 super(port, baudRate); 091 } 092 093 /** 094 * Class constructor. Instantiates a new {@code XBeeDevice} object 095 * physically connected to the given port name and configured to communicate 096 * with the provided serial settings. 097 * 098 * @param port Serial port name where XBee device is attached to. 099 * @param baudRate Serial port baud rate to communicate with the device. 100 * @param dataBits Serial port data bits. 101 * @param stopBits Serial port data bits. 102 * @param parity Serial port data bits. 103 * @param flowControl Serial port data bits. 104 * 105 * @throws IllegalArgumentException if {@code baudRate < 0} or 106 * if {@code dataBits < 0} or 107 * if {@code stopBits < 0} or 108 * if {@code parity < 0} or 109 * if {@code flowControl < 0}. 110 * @throws NullPointerException if {@code port == null}. 111 * 112 * @see #XBeeDevice(IConnectionInterface) 113 * @see #XBeeDevice(String, int) 114 * @see #XBeeDevice(String, SerialPortParameters) 115 */ 116 public XBeeDevice(String port, int baudRate, int dataBits, int stopBits, int parity, int flowControl) { 117 super(port, baudRate, dataBits, stopBits, parity, flowControl); 118 } 119 120 /** 121 * Class constructor. Instantiates a new {@code XBeeDevice} object 122 * physically connected to the given port name and configured to communicate 123 * with the provided serial settings. 124 * 125 * @param port Serial port name where XBee device is attached to. 126 * @param serialPortParameters Object containing the serial port parameters. 127 * 128 * @throws NullPointerException if {@code port == null} or 129 * if {@code serialPortParameters == null}. 130 * 131 * @see #XBeeDevice(IConnectionInterface) 132 * @see #XBeeDevice(String, int) 133 * @see #XBeeDevice(String, int, int, int, int, int) 134 * @see com.digi.xbee.api.connection.serial.SerialPortParameters 135 */ 136 public XBeeDevice(String port, SerialPortParameters serialPortParameters) { 137 super(port, serialPortParameters); 138 } 139 140 /** 141 * Class constructor. Instantiates a new {@code XBeeDevice} object with the 142 * given connection interface. 143 * 144 * @param connectionInterface The connection interface with the physical 145 * XBee device. 146 * 147 * @throws NullPointerException if {@code connectionInterface == null}. 148 * 149 * @see #XBeeDevice(String, int) 150 * @see #XBeeDevice(String, SerialPortParameters) 151 * @see #XBeeDevice(String, int, int, int, int, int) 152 * @see com.digi.xbee.api.connection.IConnectionInterface 153 */ 154 public XBeeDevice(IConnectionInterface connectionInterface) { 155 super(connectionInterface); 156 } 157 158 /** 159 * Opens the connection interface associated with this XBee device. 160 * 161 * <p>When opening the device an information reading process is 162 * automatically performed. This includes:</p> 163 * 164 * <ul> 165 * <li>64-bit address.</li> 166 * <li>Node Identifier.</li> 167 * <li>Hardware version.</li> 168 * <li>Firmware version.</li> 169 * <li>XBee device protocol.</li> 170 * <li>16-bit address (not for DigiMesh modules).</li> 171 * </ul> 172 * 173 * @throws InterfaceAlreadyOpenException if this device connection is 174 * already open. 175 * @throws XBeeException if there is any problem opening this device 176 * connection. 177 * 178 * @see #close() 179 * @see #isOpen() 180 */ 181 public void open() throws XBeeException { 182 logger.info(toString() + "Opening the connection interface..."); 183 184 // First, verify that the connection is not already open. 185 if (connectionInterface.isOpen()) 186 throw new InterfaceAlreadyOpenException(); 187 188 // Connect the interface. 189 connectionInterface.open(); 190 191 logger.info(toString() + "Connection interface open."); 192 193 // Initialize the data reader. 194 dataReader = new DataReader(connectionInterface, operatingMode, this); 195 dataReader.start(); 196 197 // Wait 10 milliseconds until the dataReader thread is started. 198 // This is because when the connection is opened immediately after 199 // closing it, there is sometimes a concurrency problem and the 200 // dataReader thread never dies. 201 try { 202 Thread.sleep(10); 203 } catch (InterruptedException e) {} 204 205 // Determine the operating mode of the XBee device if it is unknown. 206 if (operatingMode == OperatingMode.UNKNOWN) 207 operatingMode = determineOperatingMode(); 208 209 // Check if the operating mode is a valid and supported one. 210 if (operatingMode == OperatingMode.UNKNOWN) { 211 close(); 212 throw new InvalidOperatingModeException("Could not determine operating mode."); 213 } else if (operatingMode == OperatingMode.AT) { 214 close(); 215 throw new InvalidOperatingModeException(operatingMode); 216 } 217 218 // Read the device info (obtain its parameters and protocol). 219 readDeviceInfo(); 220 } 221 222 /** 223 * Closes the connection interface associated with this XBee device. 224 * 225 * @see #isOpen() 226 * @see #open() 227 */ 228 public void close() { 229 // Stop XBee reader. 230 if (dataReader != null && dataReader.isRunning()) 231 dataReader.stopReader(); 232 // Close interface. 233 connectionInterface.close(); 234 logger.info(toString() + "Connection interface closed."); 235 } 236 237 /** 238 * Returns whether the connection interface associated to this device is 239 * already open. 240 * 241 * @return {@code true} if the interface is open, {@code false} otherwise. 242 * 243 * @see #close() 244 * @see #open() 245 */ 246 public boolean isOpen() { 247 if (connectionInterface != null) 248 return connectionInterface.isOpen(); 249 return false; 250 } 251 252 /** 253 * Always returns {@code false}, since this is always a local device. 254 * 255 * @return {@code false} since it is a local device. 256 */ 257 @Override 258 public boolean isRemote() { 259 return false; 260 } 261 262 /** 263 * Returns the network associated with this XBee device. 264 * 265 * @return The XBee network of the device. 266 * 267 * @throws InterfaceNotOpenException if this device connection is not open. 268 * 269 * @see XBeeNetwork 270 */ 271 public XBeeNetwork getNetwork() { 272 if (!isOpen()) 273 throw new InterfaceNotOpenException(); 274 275 if (network == null) 276 network = new XBeeNetwork(this); 277 return network; 278 } 279 280 /** 281 * Returns the Operating mode (AT, API or API escaped) of this XBee device. 282 * 283 * @return The operating mode of this XBee device. 284 * 285 * @see com.digi.xbee.api.models.OperatingMode 286 */ 287 @Override 288 public OperatingMode getOperatingMode() { 289 return super.getOperatingMode(); 290 } 291 292 /* 293 * (non-Javadoc) 294 * @see com.digi.xbee.api.AbstractXBeeDevice#getNextFrameID() 295 */ 296 @Override 297 protected int getNextFrameID() { 298 return super.getNextFrameID(); 299 } 300 301 /** 302 * Returns this XBee device configured timeout for receiving packets in 303 * synchronous operations. 304 * 305 * @return The current receive timeout in milliseconds. 306 * 307 * @see #setReceiveTimeout(int) 308 */ 309 public int getReceiveTimeout() { 310 return receiveTimeout; 311 } 312 313 /** 314 * Configures this XBee device timeout in milliseconds for receiving 315 * packets in synchronous operations. 316 * 317 * @param receiveTimeout The new receive timeout in milliseconds. 318 * 319 * @throws IllegalArgumentException if {@code receiveTimeout < 0}. 320 * 321 * @see #getReceiveTimeout() 322 */ 323 public void setReceiveTimeout(int receiveTimeout) { 324 if (receiveTimeout < 0) 325 throw new IllegalArgumentException("Receive timeout cannot be less than 0."); 326 327 this.receiveTimeout = receiveTimeout; 328 } 329 330 /** 331 * Determines the operating mode of this XBee device. 332 * 333 * @return The operating mode of the XBee device. 334 * 335 * @throws InterfaceNotOpenException if this device connection is not open. 336 * @throws OperationNotSupportedException if the packet is being sent from 337 * a remote device. 338 * 339 * @see com.digi.xbee.api.models.OperatingMode 340 */ 341 protected OperatingMode determineOperatingMode() throws OperationNotSupportedException { 342 try { 343 // Check if device is in API or API Escaped operating modes. 344 operatingMode = OperatingMode.API; 345 dataReader.setXBeeReaderMode(operatingMode); 346 347 ATCommandResponse response = sendATCommand(new ATCommand("AP")); 348 if (response.getResponse() != null && response.getResponse().length > 0) { 349 if (response.getResponse()[0] != OperatingMode.API.getID()) 350 operatingMode = OperatingMode.API_ESCAPE; 351 logger.debug(toString() + "Using {}.", operatingMode.getName()); 352 return operatingMode; 353 } 354 } catch (TimeoutException e) { 355 // Check if device is in AT operating mode. 356 operatingMode = OperatingMode.AT; 357 dataReader.setXBeeReaderMode(operatingMode); 358 359 try { 360 // It is necessary to wait at least 1 second to enter in 361 // command mode after sending any data to the device. 362 Thread.sleep(TIMEOUT_BEFORE_COMMAND_MODE); 363 // Try to enter in AT command mode, if so the module is in AT mode. 364 boolean success = enterATCommandMode(); 365 if (success) 366 return OperatingMode.AT; 367 } catch (TimeoutException e1) { 368 logger.error(e1.getMessage(), e1); 369 } catch (InvalidOperatingModeException e1) { 370 logger.error(e1.getMessage(), e1); 371 } catch (InterruptedException e1) { 372 logger.error(e1.getMessage(), e1); 373 } 374 } catch (InvalidOperatingModeException e) { 375 logger.error("Invalid operating mode", e); 376 } catch (IOException e) { 377 logger.error(e.getMessage(), e); 378 } 379 return OperatingMode.UNKNOWN; 380 } 381 382 /** 383 * Attempts to put this device in AT Command mode. Only valid if device is 384 * working in AT mode. 385 * 386 * @return {@code true} if the device entered in AT command mode, 387 * {@code false} otherwise. 388 * 389 * @throws InterfaceNotOpenException if this device connection is not open. 390 * @throws InvalidOperatingModeException if the operating mode cannot be 391 * determined or is not supported. 392 * @throws TimeoutException if the configured time for this device expires. 393 */ 394 private boolean enterATCommandMode() throws InvalidOperatingModeException, TimeoutException { 395 if (!connectionInterface.isOpen()) 396 throw new InterfaceNotOpenException(); 397 if (operatingMode != OperatingMode.AT) 398 throw new InvalidOperatingModeException("Invalid mode. Command mode can be only accessed while in AT mode."); 399 400 // Enter in AT command mode (send '+++'). The process waits 1,5 seconds for the 'OK\n'. 401 byte[] readData = new byte[256]; 402 try { 403 // Send the command mode sequence. 404 connectionInterface.writeData(COMMAND_MODE_CHAR.getBytes()); 405 connectionInterface.writeData(COMMAND_MODE_CHAR.getBytes()); 406 connectionInterface.writeData(COMMAND_MODE_CHAR.getBytes()); 407 408 // Wait some time to let the module generate a response. 409 Thread.sleep(TIMEOUT_ENTER_COMMAND_MODE); 410 411 // Read data from the device (it should answer with 'OK\r'). 412 int readBytes = connectionInterface.readData(readData); 413 if (readBytes < COMMAND_MODE_OK.length()) 414 throw new TimeoutException(); 415 416 // Check if the read data is 'OK\r'. 417 String readString = new String(readData, 0, readBytes); 418 if (!readString.contains(COMMAND_MODE_OK)) 419 return false; 420 421 // Read data was 'OK\r'. 422 return true; 423 } catch (IOException e) { 424 logger.error(e.getMessage(), e); 425 } catch (InterruptedException e) { 426 logger.error(e.getMessage(), e); 427 } 428 return false; 429 } 430 431 /* 432 * (non-Javadoc) 433 * @see com.digi.xbee.api.AbstractXBeeDevice#addPacketListener(com.digi.xbee.api.listeners.IPacketReceiveListener) 434 */ 435 @Override 436 public void addPacketListener(IPacketReceiveListener listener) { 437 super.addPacketListener(listener); 438 } 439 440 /* 441 * (non-Javadoc) 442 * @see com.digi.xbee.api.AbstractXBeeDevice#removePacketListener(com.digi.xbee.api.listeners.IPacketReceiveListener) 443 */ 444 @Override 445 public void removePacketListener(IPacketReceiveListener listener) { 446 super.removePacketListener(listener); 447 } 448 449 /* 450 * (non-Javadoc) 451 * @see com.digi.xbee.api.AbstractXBeeDevice#addDataListener(com.digi.xbee.api.listeners.IDataReceiveListener) 452 */ 453 @Override 454 public void addDataListener(IDataReceiveListener listener) { 455 super.addDataListener(listener); 456 } 457 458 /* 459 * (non-Javadoc) 460 * @see com.digi.xbee.api.AbstractXBeeDevice#removeDataListener(com.digi.xbee.api.listeners.IDataReceiveListener) 461 */ 462 @Override 463 public void removeDataListener(IDataReceiveListener listener) { 464 super.removeDataListener(listener); 465 } 466 467 /* 468 * (non-Javadoc) 469 * @see com.digi.xbee.api.AbstractXBeeDevice#addIOSampleListener(com.digi.xbee.api.listeners.IIOSampleReceiveListener) 470 */ 471 @Override 472 public void addIOSampleListener(IIOSampleReceiveListener listener) { 473 super.addIOSampleListener(listener); 474 } 475 476 /* 477 * (non-Javadoc) 478 * @see com.digi.xbee.api.AbstractXBeeDevice#removeIOSampleListener(com.digi.xbee.api.listeners.IIOSampleReceiveListener) 479 */ 480 @Override 481 public void removeIOSampleListener(IIOSampleReceiveListener listener) { 482 super.removeIOSampleListener(listener); 483 } 484 485 /* 486 * (non-Javadoc) 487 * @see com.digi.xbee.api.AbstractXBeeDevice#addModemStatusListener(com.digi.xbee.api.listeners.IModemStatusReceiveListener) 488 */ 489 @Override 490 public void addModemStatusListener(IModemStatusReceiveListener listener) { 491 super.addModemStatusListener(listener); 492 } 493 494 /* 495 * (non-Javadoc) 496 * @see com.digi.xbee.api.AbstractXBeeDevice#removeModemStatusListener(com.digi.xbee.api.listeners.IModemStatusReceiveListener) 497 */ 498 @Override 499 public void removeModemStatusListener(IModemStatusReceiveListener listener) { 500 super.removeModemStatusListener(listener); 501 } 502 503 /** 504 * Sends asynchronously the provided data to the XBee device of the network 505 * corresponding to the given 64-bit address. 506 * 507 * <p>Asynchronous transmissions do not wait for answer from the remote 508 * device or for transmit status packet.</p> 509 * 510 * @param address The 64-bit address of the XBee that will receive the data. 511 * @param data Byte array containing the data to be sent. 512 * 513 * @throws InterfaceNotOpenException if this device connection is not open. 514 * @throws NullPointerException if {@code address == null} or 515 * if {@code data == null}. 516 * @throws XBeeException if there is any XBee related exception. 517 * 518 * @see #sendData(RemoteXBeeDevice, byte[]) 519 * @see #sendData(XBee64BitAddress, byte[]) 520 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 521 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 522 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 523 * @see com.digi.xbee.api.models.XBee64BitAddress 524 */ 525 protected void sendDataAsync(XBee64BitAddress address, byte[] data) throws XBeeException { 526 // Verify the parameters are not null, if they are null, throw an exception. 527 if (address == null) 528 throw new NullPointerException("Address cannot be null"); 529 if (data == null) 530 throw new NullPointerException("Data cannot be null"); 531 532 // Check connection. 533 if (!connectionInterface.isOpen()) 534 throw new InterfaceNotOpenException(); 535 // Check if device is remote. 536 if (isRemote()) 537 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 538 539 logger.debug(toString() + "Sending data asynchronously to {} >> {}.", address, HexUtils.prettyHexString(data)); 540 541 XBeePacket xbeePacket; 542 switch (getXBeeProtocol()) { 543 case RAW_802_15_4: 544 xbeePacket = new TX64Packet(getNextFrameID(), address, XBeeTransmitOptions.NONE, data); 545 break; 546 default: 547 xbeePacket = new TransmitPacket(getNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, 0, XBeeTransmitOptions.NONE, data); 548 } 549 sendAndCheckXBeePacket(xbeePacket, true); 550 } 551 552 /** 553 * Sends asynchronously the provided data to the XBee device of the network 554 * corresponding to the given 64-bit/16-bit address. 555 * 556 * <p>Asynchronous transmissions do not wait for answer from the remote 557 * device or for transmit status packet.</p> 558 * 559 * @param address64Bit The 64-bit address of the XBee that will receive the 560 * data. 561 * @param address16bit The 16-bit address of the XBee that will receive the 562 * data. If it is unknown the 563 * {@code XBee16BitAddress.UNKNOWN_ADDRESS} must be 564 * used. 565 * @param data Byte array containing the data to be sent. 566 * 567 * @throws InterfaceNotOpenException if this device connection is not open. 568 * @throws NullPointerException if {@code address64Bit == null} or 569 * if {@code address16bit == null} or 570 * if {@code data == null}. 571 * @throws XBeeException if a remote device is trying to send data or 572 * if there is any other XBee related exception. 573 * 574 * @see #getReceiveTimeout() 575 * @see #setReceiveTimeout(int) 576 * @see #sendData(RemoteXBeeDevice, byte[]) 577 * @see #sendData(XBee64BitAddress, byte[]) 578 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 579 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 580 * @see #sendDataAsync(XBee64BitAddress, byte[]) 581 * @see com.digi.xbee.api.models.XBee16BitAddress 582 * @see com.digi.xbee.api.models.XBee64BitAddress 583 */ 584 protected void sendDataAsync(XBee64BitAddress address64Bit, XBee16BitAddress address16bit, byte[] data) throws XBeeException { 585 // Verify the parameters are not null, if they are null, throw an exception. 586 if (address64Bit == null) 587 throw new NullPointerException("64-bit address cannot be null"); 588 if (address16bit == null) 589 throw new NullPointerException("16-bit address cannot be null"); 590 if (data == null) 591 throw new NullPointerException("Data cannot be null"); 592 593 // Check connection. 594 if (!connectionInterface.isOpen()) 595 throw new InterfaceNotOpenException(); 596 // Check if device is remote. 597 if (isRemote()) 598 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 599 600 logger.debug(toString() + "Sending data asynchronously to {}[{}] >> {}.", 601 address64Bit, address16bit, HexUtils.prettyHexString(data)); 602 603 XBeePacket xbeePacket = new TransmitPacket(getNextFrameID(), address64Bit, address16bit, 0, XBeeTransmitOptions.NONE, data); 604 sendAndCheckXBeePacket(xbeePacket, true); 605 } 606 607 /** 608 * Sends the provided data to the provided XBee device asynchronously. 609 * 610 * <p>Asynchronous transmissions do not wait for answer from the remote 611 * device or for transmit status packet.</p> 612 * 613 * @param xbeeDevice The XBee device of the network that will receive the 614 * data. 615 * @param data Byte array containing the data to be sent. 616 * 617 * @throws InterfaceNotOpenException if this device connection is not open. 618 * @throws NullPointerException if {@code xbeeDevice == null} or 619 * if {@code data == null}. 620 * @throws XBeeException if there is any XBee related exception. 621 * 622 * @see #sendData(RemoteXBeeDevice, byte[]) 623 * @see RemoteXBeeDevice 624 */ 625 public void sendDataAsync(RemoteXBeeDevice xbeeDevice, byte[] data) throws XBeeException { 626 if (xbeeDevice == null) 627 throw new NullPointerException("Remote XBee device cannot be null"); 628 sendDataAsync(xbeeDevice.get64BitAddress(), data); 629 } 630 631 /** 632 * Sends the provided data to the XBee device of the network corresponding 633 * to the given 64-bit address. 634 * 635 * <p>This method blocks till a success or error response arrives or the 636 * configured receive timeout expires.</p> 637 * 638 * <p>The received timeout is configured using the {@code setReceiveTimeout} 639 * method and can be consulted with {@code getReceiveTimeout} method.</p> 640 * 641 * <p>For non-blocking operations use the method 642 * {@link #sendData(XBee64BitAddress, byte[])}.</p> 643 * 644 * @param address The 64-bit address of the XBee that will receive the data. 645 * @param data Byte array containing the data to be sent. 646 * 647 * @throws InterfaceNotOpenException if this device connection is not open. 648 * @throws NullPointerException if {@code address == null} or 649 * if {@code data == null}. 650 * @throws TimeoutException if there is a timeout sending the data. 651 * @throws XBeeException if there is any other XBee related exception. 652 * 653 * @see #getReceiveTimeout() 654 * @see #setReceiveTimeout(int) 655 * @see #sendData(RemoteXBeeDevice, byte[]) 656 * @see #sendData(XBee64BitAddress, XBee16BitAddress, byte[]) 657 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 658 * @see #sendDataAsync(XBee64BitAddress, byte[]) 659 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 660 * @see com.digi.xbee.api.models.XBee64BitAddress 661 */ 662 protected void sendData(XBee64BitAddress address, byte[] data) throws TimeoutException, XBeeException { 663 // Verify the parameters are not null, if they are null, throw an exception. 664 if (address == null) 665 throw new NullPointerException("Address cannot be null"); 666 if (data == null) 667 throw new NullPointerException("Data cannot be null"); 668 669 // Check connection. 670 if (!connectionInterface.isOpen()) 671 throw new InterfaceNotOpenException(); 672 // Check if device is remote. 673 if (isRemote()) 674 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 675 676 logger.debug(toString() + "Sending data to {} >> {}.", address, HexUtils.prettyHexString(data)); 677 678 XBeePacket xbeePacket; 679 switch (getXBeeProtocol()) { 680 case RAW_802_15_4: 681 xbeePacket = new TX64Packet(getNextFrameID(), address, XBeeTransmitOptions.NONE, data); 682 break; 683 default: 684 xbeePacket = new TransmitPacket(getNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, 0, XBeeTransmitOptions.NONE, data); 685 } 686 sendAndCheckXBeePacket(xbeePacket, false); 687 } 688 689 /** 690 * Sends the provided data to the XBee device of the network corresponding 691 * to the given 64-bit/16-bit address. 692 * 693 * <p>This method blocks till a success or error response arrives or the 694 * configured receive timeout expires.</p> 695 * 696 * <p>The received timeout is configured using the {@code setReceiveTimeout} 697 * method and can be consulted with {@code getReceiveTimeout} method.</p> 698 * 699 * <p>For non-blocking operations use the method 700 * {@link #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[])}.</p> 701 * 702 * @param address64Bit The 64-bit address of the XBee that will receive the 703 * data. 704 * @param address16bit The 16-bit address of the XBee that will receive the 705 * data. If it is unknown the 706 * {@code XBee16BitAddress.UNKNOWN_ADDRESS} must be 707 * used. 708 * @param data Byte array containing the data to be sent. 709 * 710 * @throws InterfaceNotOpenException if this device connection is not open. 711 * @throws NullPointerException if {@code address64Bit == null} or 712 * if {@code address16bit == null} or 713 * if {@code data == null}. 714 * @throws TimeoutException if there is a timeout sending the data. 715 * @throws XBeeException if a remote device is trying to send data or 716 * if there is any other XBee related exception. 717 * 718 * @see #getReceiveTimeout() 719 * @see #setReceiveTimeout(int) 720 * @see #sendData(RemoteXBeeDevice, byte[]) 721 * @see #sendData(XBee64BitAddress, byte[]) 722 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 723 * @see #sendDataAsync(XBee64BitAddress, byte[]) 724 * @see #sendDataAsync(XBee64BitAddress, XBee16BitAddress, byte[]) 725 * @see com.digi.xbee.api.models.XBee16BitAddress 726 * @see com.digi.xbee.api.models.XBee64BitAddress 727 */ 728 protected void sendData(XBee64BitAddress address64Bit, XBee16BitAddress address16bit, byte[] data) throws TimeoutException, XBeeException { 729 // Verify the parameters are not null, if they are null, throw an exception. 730 if (address64Bit == null) 731 throw new NullPointerException("64-bit address cannot be null"); 732 if (address16bit == null) 733 throw new NullPointerException("16-bit address cannot be null"); 734 if (data == null) 735 throw new NullPointerException("Data cannot be null"); 736 737 // Check connection. 738 if (!connectionInterface.isOpen()) 739 throw new InterfaceNotOpenException(); 740 // Check if device is remote. 741 if (isRemote()) 742 throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device."); 743 744 logger.debug(toString() + "Sending data to {}[{}] >> {}.", 745 address64Bit, address16bit, HexUtils.prettyHexString(data)); 746 747 XBeePacket xbeePacket = new TransmitPacket(getNextFrameID(), address64Bit, address16bit, 0, XBeeTransmitOptions.NONE, data); 748 sendAndCheckXBeePacket(xbeePacket, false); 749 } 750 751 /** 752 * Sends the provided data to the given XBee device choosing the optimal 753 * send method depending on the protocol of the local XBee device. 754 * 755 * <p>This method blocks till a success or error response arrives or the 756 * configured receive timeout expires.</p> 757 * 758 * <p>The received timeout is configured using the {@code setReceiveTimeout} 759 * method and can be consulted with {@code getReceiveTimeout} method.</p> 760 * 761 * <p>For non-blocking operations use the method 762 * {@link #sendDataAsync(RemoteXBeeDevice, byte[])}.</p> 763 * 764 * @param xbeeDevice The XBee device of the network that will receive the 765 * data. 766 * @param data Byte array containing the data to be sent. 767 * 768 * @throws InterfaceNotOpenException if this device connection is not open. 769 * @throws NullPointerException if {@code xbeeDevice == null} or 770 * if {@code data == null}. 771 * @throws TimeoutException if there is a timeout sending the data. 772 * @throws XBeeException if there is any other XBee related exception. 773 * 774 * @see #getReceiveTimeout() 775 * @see #setReceiveTimeout(int) 776 * @see #sendDataAsync(RemoteXBeeDevice, byte[]) 777 */ 778 public void sendData(RemoteXBeeDevice xbeeDevice, byte[] data) throws TimeoutException, XBeeException { 779 if (xbeeDevice == null) 780 throw new NullPointerException("Remote XBee device cannot be null"); 781 782 switch (getXBeeProtocol()) { 783 case ZIGBEE: 784 case DIGI_POINT: 785 if (xbeeDevice.get64BitAddress() != null && xbeeDevice.get16BitAddress() != null) 786 sendData(xbeeDevice.get64BitAddress(), xbeeDevice.get16BitAddress(), data); 787 else 788 sendData(xbeeDevice.get64BitAddress(), data); 789 break; 790 case RAW_802_15_4: 791 if (this instanceof Raw802Device) { 792 if (xbeeDevice.get64BitAddress() != null) 793 ((Raw802Device)this).sendData(xbeeDevice.get64BitAddress(), data); 794 else 795 ((Raw802Device)this).sendData(xbeeDevice.get16BitAddress(), data); 796 } else 797 sendData(xbeeDevice.get64BitAddress(), data); 798 break; 799 case DIGI_MESH: 800 default: 801 sendData(xbeeDevice.get64BitAddress(), data); 802 } 803 } 804 805 /** 806 * Sends the provided data to all the XBee nodes of the network (broadcast). 807 * 808 * <p>This method blocks till a success or error transmit status arrives or 809 * the configured receive timeout expires.</p> 810 * 811 * <p>The received timeout is configured using the {@code setReceiveTimeout} 812 * method and can be consulted with {@code getReceiveTimeout} method.</p> 813 * 814 * @param data Byte array containing the data to be sent. 815 * 816 * @throws InterfaceNotOpenException if this device connection is not open. 817 * @throws NullPointerException if {@code data == null}. 818 * @throws TimeoutException if there is a timeout sending the data. 819 * @throws XBeeException if there is any other XBee related exception. 820 * 821 * @see #getReceiveTimeout() 822 * @see #setReceiveTimeout(int) 823 */ 824 public void sendBroadcastData(byte[] data) throws TimeoutException, XBeeException { 825 sendData(XBee64BitAddress.BROADCAST_ADDRESS, data); 826 } 827 828 /** 829 * Sends the given XBee packet and registers the given packet listener 830 * (if not {@code null}) to be notified when the answers is received. 831 * 832 * <p>This is a non-blocking operation. To wait for the answer use 833 * {@code sendPacket(XBeePacket)}.</p> 834 * 835 * @param packet XBee packet to be sent. 836 * @param packetReceiveListener Listener for the operation, {@code null} 837 * not to be notified when the answer arrives. 838 * 839 * @throws InterfaceNotOpenException if this device connection is not open. 840 * @throws NullPointerException if {@code packet == null}. 841 * @throws XBeeException if there is any other XBee related exception. 842 * 843 * @see #sendPacket(XBeePacket) 844 * @see #sendPacketAsync(XBeePacket) 845 * @see com.digi.xbee.api.listeners.IPacketReceiveListener 846 * @see com.digi.xbee.api.packet.XBeePacket 847 */ 848 public void sendPacket(XBeePacket packet, IPacketReceiveListener packetReceiveListener) throws XBeeException { 849 try { 850 sendXBeePacket(packet, packetReceiveListener); 851 } catch (IOException e) { 852 throw new XBeeException("Error writing in the communication interface.", e); 853 } 854 } 855 856 /** 857 * Sends the given XBee packet asynchronously. 858 * 859 * <p>This is a non-blocking operation that do not wait for the answer and 860 * is never notified when it arrives.</p> 861 * 862 * <p>To be notified when the answer is received, use 863 * {@link #sendXBeePacket(XBeePacket, IPacketReceiveListener)}.</p> 864 * 865 * @param packet XBee packet to be sent asynchronously. 866 * 867 * @throws InterfaceNotOpenException if this device connection is not open. 868 * @throws NullPointerException if {@code packet == null}. 869 * @throws XBeeException if there is any other XBee related exception. 870 * 871 * @see #sendXBeePacket(XBeePacket) 872 * @see #sendXBeePacket(XBeePacket, IPacketReceiveListener) 873 * @see com.digi.xbee.api.packet.XBeePacket 874 */ 875 public void sendPacketAsync(XBeePacket packet) throws XBeeException { 876 try { 877 super.sendXBeePacket(packet, null); 878 } catch (IOException e) { 879 throw new XBeeException("Error writing in the communication interface.", e); 880 } 881 } 882 883 /** 884 * Sends the given XBee packet synchronously and blocks until the response 885 * is received or the configured receive timeout expires. 886 * 887 * <p>The received timeout is configured using the {@code setReceiveTimeout} 888 * method and can be consulted with {@code getReceiveTimeout} method.</p> 889 * 890 * <p>Use {@code sendXBeePacketAsync(XBeePacket)} or 891 * {@code #sendXBeePacket(XBeePacket, IPacketReceiveListener)} for 892 * non-blocking operations.</p> 893 * 894 * @param packet XBee packet to be sent. 895 * 896 * @return An {@code XBeePacket} object containing the response of the sent 897 * packet or {@code null} if there is no response. 898 * 899 * @throws InterfaceNotOpenException if this device connection is not open. 900 * @throws NullPointerException if {@code packet == null}. 901 * @throws TimeoutException if there is a timeout sending the XBee packet. 902 * @throws XBeeException if there is any other XBee related exception. 903 * 904 * @see #getReceiveTimeout() 905 * @see #sendXBeePacket(XBeePacket, IPacketReceiveListener) 906 * @see #sendXBeePacketAsync(XBeePacket) 907 * @see #setReceiveTimeout(int) 908 * @see com.digi.xbee.api.packet.XBeePacket 909 */ 910 public XBeePacket sendPacket(XBeePacket packet) throws TimeoutException, XBeeException { 911 try { 912 return super.sendXBeePacket(packet); 913 } catch (IOException e) { 914 throw new XBeeException("Error writing in the communication interface.", e); 915 } 916 } 917 918 /** 919 * Waits until a Modem Status packet with a reset status, 920 * {@code ModemStatusEvent.STATUS_HARDWARE_RESET} (0x00), or a watchdog 921 * timer reset, {@code ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET} (0x01), 922 * is received or the timeout expires. 923 * 924 * @return {@code true} if the Modem Status packet is received, 925 * {@code false} otherwise. 926 * 927 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_HARDWARE_RESET 928 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_WATCHDOG_TIMER_RESET 929 */ 930 private boolean waitForModemResetStatusPacket() { 931 modemStatusReceived = false; 932 addModemStatusListener(resetStatusListener); 933 synchronized (resetLock) { 934 try { 935 resetLock.wait(TIMEOUT_RESET); 936 } catch (InterruptedException e) { } 937 } 938 removeModemStatusListener(resetStatusListener); 939 return modemStatusReceived; 940 } 941 942 /** 943 * Custom listener for modem reset packets. 944 * 945 * <p>When a Modem Status packet is received with status 946 * {@code ModemStatusEvent.STATUS_HARDWARE_RESET} or 947 * {@code ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET}, it 948 * notifies the object that was waiting for the reception.</p> 949 * 950 * @see com.digi.xbee.api.listeners.IModemStatusReceiveListener 951 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_HARDWARE_RESET 952 * @see com.digi.xbee.api.models.ModemStatusEvent#STATUS_WATCHDOG_TIMER_RESET 953 */ 954 private IModemStatusReceiveListener resetStatusListener = new IModemStatusReceiveListener() { 955 956 /* 957 * (non-Javadoc) 958 * @see com.digi.xbee.api.listeners.IModemStatusReceiveListener#modemStatusEventReceived(com.digi.xbee.api.models.ModemStatusEvent) 959 */ 960 @Override 961 public void modemStatusEventReceived(ModemStatusEvent modemStatusEvent) { 962 if (modemStatusEvent == ModemStatusEvent.STATUS_HARDWARE_RESET 963 || modemStatusEvent == ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET){ 964 modemStatusReceived = true; 965 // Continue execution by notifying the lock object. 966 synchronized (resetLock) { 967 resetLock.notify(); 968 } 969 } 970 } 971 }; 972 973 /* 974 * (non-Javadoc) 975 * @see com.digi.xbee.api.AbstractXBeeDevice#reset() 976 */ 977 @Override 978 public void reset() throws TimeoutException, XBeeException { 979 // Check connection. 980 if (!connectionInterface.isOpen()) 981 throw new InterfaceNotOpenException(); 982 983 logger.info(toString() + "Resetting the local module..."); 984 985 ATCommandResponse response = null; 986 try { 987 response = sendATCommand(new ATCommand("FR")); 988 } catch (IOException e) { 989 throw new XBeeException("Error writing in the communication interface.", e); 990 } 991 992 // Check if AT Command response is valid. 993 checkATCommandResponseIsValid(response); 994 995 // Wait for a Modem Status packet. 996 if (!waitForModemResetStatusPacket()) 997 throw new TimeoutException("Timeout waiting for the Modem Status packet."); 998 999 logger.info(toString() + "Module reset successfully."); 1000 } 1001 1002 /** 1003 * Reads new data received by this XBee device during the configured 1004 * received timeout. 1005 * 1006 * <p>This method blocks until new data is received or the configured 1007 * receive timeout expires.</p> 1008 * 1009 * <p>The received timeout is configured using the {@code setReceiveTimeout} 1010 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1011 * 1012 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1013 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1014 * 1015 * @return An {@code XBeeMessage} object containing the data and the source 1016 * address of the remote node that sent the data. {@code null} if 1017 * this did not receive new data during the configured receive 1018 * timeout. 1019 * 1020 * @throws InterfaceNotOpenException if this device connection is not open. 1021 * 1022 * @see #readData(int) 1023 * @see #getReceiveTimeout() 1024 * @see #setReceiveTimeout(int) 1025 * @see #readDataFrom(RemoteXBeeDevice) 1026 * @see #readDataFrom(RemoteXBeeDevice, int) 1027 * @see com.digi.xbee.api.models.XBeeMessage 1028 */ 1029 public XBeeMessage readData() { 1030 return readDataPacket(null, TIMEOUT_READ_PACKET); 1031 } 1032 1033 /** 1034 * Reads new data received by this XBee device during the provided timeout. 1035 * 1036 * <p>This method blocks until new data is received or the provided timeout 1037 * expires.</p> 1038 * 1039 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1040 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1041 * 1042 * @param timeout The time to wait for new data in milliseconds. 1043 * 1044 * @return An {@code XBeeMessage} object containing the data and the source 1045 * address of the remote node that sent the data. {@code null} if 1046 * this device did not receive new data during {@code timeout} 1047 * milliseconds. 1048 * 1049 * @throws IllegalArgumentException if {@code timeout < 0}. 1050 * @throws InterfaceNotOpenException if this device connection is not open. 1051 * 1052 * @see #readData() 1053 * @see #readDataFrom(RemoteXBeeDevice) 1054 * @see #readDataFrom(RemoteXBeeDevice, int) 1055 * @see com.digi.xbee.api.models.XBeeMessage 1056 */ 1057 public XBeeMessage readData(int timeout) { 1058 if (timeout < 0) 1059 throw new IllegalArgumentException("Read timeout must be 0 or greater."); 1060 1061 return readDataPacket(null, timeout); 1062 } 1063 1064 /** 1065 * Reads new data received from the given remote XBee device during the 1066 * configured received timeout. 1067 * 1068 * <p>This method blocks until new data from the provided remote XBee 1069 * device is received or the configured receive timeout expires.</p> 1070 * 1071 * <p>The received timeout is configured using the {@code setReceiveTimeout} 1072 * method and can be consulted with {@code getReceiveTimeout} method.</p> 1073 * 1074 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1075 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1076 * 1077 * @param remoteXBeeDevice The remote device to read data from. 1078 * 1079 * @return An {@code XBeeMessage} object containing the data and the source 1080 * address of the remote node that sent the data. {@code null} if 1081 * this device did not receive new data from the provided remote 1082 * XBee device during the configured receive timeout. 1083 * 1084 * @throws InterfaceNotOpenException if this device connection is not open. 1085 * @throws NullPointerException if {@code remoteXBeeDevice == null}. 1086 * 1087 * @see #readDataFrom(RemoteXBeeDevice, int) 1088 * @see #getReceiveTimeout() 1089 * @see #setReceiveTimeout(int) 1090 * @see #readData() 1091 * @see #readData(int) 1092 * @see RemoteXBeeDevice 1093 * @see com.digi.xbee.api.models.XBeeMessage 1094 */ 1095 public XBeeMessage readDataFrom(RemoteXBeeDevice remoteXBeeDevice) { 1096 if (remoteXBeeDevice == null) 1097 throw new NullPointerException("Remote XBee device cannot be null."); 1098 1099 return readDataPacket(remoteXBeeDevice, TIMEOUT_READ_PACKET); 1100 } 1101 1102 /** 1103 * Reads new data received from the given remote XBee device during the 1104 * provided timeout. 1105 * 1106 * <p>This method blocks until new data from the provided remote XBee 1107 * device is received or the given timeout expires.</p> 1108 * 1109 * <p>For non-blocking operations, register a {@code IDataReceiveListener} 1110 * using the method {@link #addDataListener(IDataReceiveListener)}.</p> 1111 * 1112 * @param remoteXBeeDevice The remote device to read data from. 1113 * @param timeout The time to wait for new data in milliseconds. 1114 * 1115 * @return An {@code XBeeMessage} object containing the data and the source 1116 * address of the remote node that sent the data. {@code null} if 1117 * this device did not receive new data from the provided remote 1118 * XBee device during {@code timeout} milliseconds. 1119 * 1120 * @throws IllegalArgumentException if {@code timeout < 0}. 1121 * @throws InterfaceNotOpenException if this device connection is not open. 1122 * @throws NullPointerException if {@code remoteXBeeDevice == null}. 1123 * 1124 * @see #readDataFrom(RemoteXBeeDevice) 1125 * @see #getReceiveTimeout() 1126 * @see #setReceiveTimeout(int) 1127 * @see #readData() 1128 * @see #readData(int) 1129 * @see RemoteXBeeDevice 1130 * @see com.digi.xbee.api.models.XBeeMessage 1131 */ 1132 public XBeeMessage readDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) { 1133 if (remoteXBeeDevice == null) 1134 throw new NullPointerException("Remote XBee device cannot be null."); 1135 if (timeout < 0) 1136 throw new IllegalArgumentException("Read timeout must be 0 or greater."); 1137 1138 return readDataPacket(remoteXBeeDevice, timeout); 1139 } 1140 1141 /** 1142 * Reads a new data packet received by this XBee device during the provided 1143 * timeout. 1144 * 1145 * <p>This method blocks until new data is received or the given timeout 1146 * expires.</p> 1147 * 1148 * <p>If the provided remote XBee device is {@code null} the method returns 1149 * the first data packet read from any remote device. 1150 * <br> 1151 * If it the remote device is not {@code null} the method returns the first 1152 * data package read from the provided device. 1153 * </p> 1154 * 1155 * @param remoteXBeeDevice The remote device to get a data packet from. 1156 * {@code null} to read a data packet sent by any 1157 * remote XBee device. 1158 * @param timeout The time to wait for a data packet in milliseconds. 1159 * 1160 * @return An {@code XBeeMessage} received by this device, containing the 1161 * data and the source address of the remote node that sent the 1162 * data. {@code null} if this device did not receive new data 1163 * during {@code timeout} milliseconds. 1164 * 1165 * @throws InterfaceNotOpenException if this device connection is not open. 1166 * 1167 * @see RemoteXBeeDevice 1168 * @see com.digi.xbee.api.models.XBeeMessage 1169 */ 1170 private XBeeMessage readDataPacket(RemoteXBeeDevice remoteXBeeDevice, int timeout) { 1171 // Check connection. 1172 if (!connectionInterface.isOpen()) 1173 throw new InterfaceNotOpenException(); 1174 1175 XBeePacketsQueue xbeePacketsQueue = dataReader.getXBeePacketsQueue(); 1176 XBeePacket xbeePacket = null; 1177 1178 if (remoteXBeeDevice != null) 1179 xbeePacket = xbeePacketsQueue.getFirstDataPacketFrom(remoteXBeeDevice, timeout); 1180 else 1181 xbeePacket = xbeePacketsQueue.getFirstDataPacket(timeout); 1182 1183 if (xbeePacket == null) 1184 return null; 1185 1186 // Obtain the source address and data from the packet. 1187 RemoteXBeeDevice remoteDevice = null; 1188 byte[] data = null; 1189 1190 APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).getFrameType(); 1191 try { 1192 switch (packetType) { 1193 case RECEIVE_PACKET: 1194 ReceivePacket receivePacket = (ReceivePacket)xbeePacket; 1195 remoteDevice = getNetwork().getDevice(receivePacket.get64bitSourceAddress()); 1196 if (remoteDevice == null) { 1197 if (remoteXBeeDevice != null) 1198 remoteDevice = remoteXBeeDevice; 1199 else 1200 remoteDevice = new RemoteXBeeDevice(this, receivePacket.get64bitSourceAddress()); 1201 getNetwork().addRemoteDevice(remoteDevice); 1202 } 1203 data = receivePacket.getRFData(); 1204 break; 1205 case RX_16: 1206 RX16Packet rx16Packet = (RX16Packet)xbeePacket; 1207 remoteDevice = getNetwork().getDevice(rx16Packet.get16bitSourceAddress()); 1208 if (remoteDevice == null) { 1209 if (remoteXBeeDevice != null) 1210 remoteDevice = remoteXBeeDevice; 1211 else 1212 remoteDevice = new RemoteRaw802Device(this, rx16Packet.get16bitSourceAddress()); 1213 getNetwork().addRemoteDevice(remoteDevice); 1214 } 1215 data = rx16Packet.getRFData(); 1216 break; 1217 case RX_64: 1218 RX64Packet rx64Packet = (RX64Packet)xbeePacket; 1219 remoteDevice = getNetwork().getDevice(rx64Packet.get64bitSourceAddress()); 1220 if (remoteDevice == null) { 1221 if (remoteXBeeDevice != null) 1222 remoteDevice = remoteXBeeDevice; 1223 else 1224 remoteDevice = new RemoteXBeeDevice(this, rx64Packet.get64bitSourceAddress()); 1225 getNetwork().addRemoteDevice(remoteDevice); 1226 } 1227 data = rx64Packet.getRFData(); 1228 break; 1229 default: 1230 return null; 1231 } 1232 } catch (XBeeException e) { 1233 logger.error(e.getMessage(), e); 1234 return null; 1235 } 1236 1237 // Create and return the XBee message. 1238 return new XBeeMessage(remoteDevice, data, ((XBeeAPIPacket)xbeePacket).isBroadcast()); 1239 } 1240 1241 /* 1242 * (non-Javadoc) 1243 * @see com.digi.xbee.api.AbstractXBeeDevice#toString() 1244 */ 1245 @Override 1246 public String toString() { 1247 String id = getNodeID() == null ? "" : getNodeID(); 1248 String addr64 = get64BitAddress() == null || get64BitAddress() == XBee64BitAddress.UNKNOWN_ADDRESS ? 1249 "" : get64BitAddress().toString(); 1250 1251 if (id.length() == 0 && addr64.length() == 0) 1252 return super.toString(); 1253 1254 StringBuilder message = new StringBuilder(super.toString()); 1255 message.append(addr64); 1256 if (id.length() > 0) { 1257 message.append(" ("); 1258 message.append(id); 1259 message.append(")"); 1260 } 1261 message.append(" - "); 1262 1263 return message.toString(); 1264 } 1265}