001/* 002 * Copyright 2017-2019, Digi International Inc. 003 * 004 * This Source Code Form is subject to the terms of the Mozilla Public 005 * License, v. 2.0. If a copy of the MPL was not distributed with this 006 * file, you can obtain one at http://mozilla.org/MPL/2.0/. 007 * 008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 015 */ 016package com.digi.xbee.api; 017 018import java.net.Inet6Address; 019 020import com.digi.xbee.api.connection.IConnectionInterface; 021import com.digi.xbee.api.connection.serial.SerialPortParameters; 022import com.digi.xbee.api.exceptions.InterfaceNotOpenException; 023import com.digi.xbee.api.exceptions.OperationNotSupportedException; 024import com.digi.xbee.api.exceptions.TimeoutException; 025import com.digi.xbee.api.exceptions.XBeeDeviceException; 026import com.digi.xbee.api.exceptions.XBeeException; 027import com.digi.xbee.api.models.AssociationIndicationStatus; 028import com.digi.xbee.api.models.CoAPURI; 029import com.digi.xbee.api.models.HTTPMethodEnum; 030import com.digi.xbee.api.models.IPProtocol; 031import com.digi.xbee.api.models.RemoteATCommandOptions; 032import com.digi.xbee.api.models.ThreadAssociationIndicationStatus; 033import com.digi.xbee.api.models.XBeeProtocol; 034import com.digi.xbee.api.packet.thread.CoAPTxRequestPacket; 035import com.digi.xbee.api.utils.ByteUtils; 036import com.digi.xbee.api.utils.HexUtils; 037 038/** 039 * This class represents a local Thread device. 040 * 041 * @see CellularDevice 042 * @see DigiPointDevice 043 * @see DigiMeshDevice 044 * @see Raw802Device 045 * @see WiFiDevice 046 * @see XBeeDevice 047 * @see ZigBeeDevice 048 * 049 * @since 1.2.1 050 */ 051public class ThreadDevice extends IPv6Device { 052 053 // Constants 054 private static final String OPERATION_EXCEPTION = "Operation not supported in Thread protocol."; 055 056 private static final String ERROR_PROTOCOL_ILLEGAL = String.format("Protocol must be %s or %s.", 057 IPProtocol.UDP.getName(), IPProtocol.COAP.getName()); 058 059 /** 060 * Class constructor. Instantiates a new {@code ThreadDevice} object in 061 * the given port name and baud rate. 062 * 063 * @param port Serial port name where Thread device is attached to. 064 * @param baudRate Serial port baud rate to communicate with the device. 065 * Other connection parameters will be set as default (8 066 * data bits, 1 stop bit, no parity, no flow control). 067 * 068 * @throws IllegalArgumentException if {@code baudRate < 0}. 069 * @throws NullPointerException if {@code port == null}. 070 * 071 * @see #ThreadDevice(IConnectionInterface) 072 * @see #ThreadDevice(String, SerialPortParameters) 073 * @see #ThreadDevice(String, int, int, int, int, int) 074 */ 075 public ThreadDevice(String port, int baudRate) { 076 this(XBee.createConnectiontionInterface(port, baudRate)); 077 } 078 079 /** 080 * Class constructor. Instantiates a new {@code ThreadDevice} object in 081 * the given serial port name and settings. 082 * 083 * @param port Serial port name where Thread device is attached to. 084 * @param baudRate Serial port baud rate to communicate with the device. 085 * @param dataBits Serial port data bits. 086 * @param stopBits Serial port data bits. 087 * @param parity Serial port data bits. 088 * @param flowControl Serial port data bits. 089 * 090 * @throws IllegalArgumentException if {@code baudRate < 0} or 091 * if {@code dataBits < 0} or 092 * if {@code stopBits < 0} or 093 * if {@code parity < 0} or 094 * if {@code flowControl < 0}. 095 * @throws NullPointerException if {@code port == null}. 096 * 097 * @see #ThreadDevice(IConnectionInterface) 098 * @see #ThreadDevice(String, int) 099 * @see #ThreadDevice(String, SerialPortParameters) 100 */ 101 public ThreadDevice(String port, int baudRate, int dataBits, int stopBits, int parity, int flowControl) { 102 this(port, new SerialPortParameters(baudRate, dataBits, stopBits, parity, flowControl)); 103 } 104 105 /** 106 * Class constructor. Instantiates a new {@code ThreadDevice} object in 107 * the given serial port name and parameters. 108 * 109 * @param port Serial port name where Thread device is attached to. 110 * @param serialPortParameters Object containing the serial port parameters. 111 * 112 * @throws NullPointerException if {@code port == null} or 113 * if {@code serialPortParameters == null}. 114 * 115 * @see #ThreadDevice(IConnectionInterface) 116 * @see #ThreadDevice(String, int) 117 * @see #ThreadDevice(String, int, int, int, int, int) 118 * @see com.digi.xbee.api.connection.serial.SerialPortParameters 119 */ 120 public ThreadDevice(String port, SerialPortParameters serialPortParameters) { 121 this(XBee.createConnectiontionInterface(port, serialPortParameters)); 122 } 123 124 /** 125 * Class constructor. Instantiates a new {@code ThreadDevice} object with 126 * the given connection interface. 127 * 128 * @param connectionInterface The connection interface with the physical 129 * Thread device. 130 * 131 * @throws NullPointerException if {@code connectionInterface == null} 132 * 133 * @see #ThreadDevice(String, int) 134 * @see #ThreadDevice(String, SerialPortParameters) 135 * @see #ThreadDevice(String, int, int, int, int, int) 136 * @see com.digi.xbee.api.connection.IConnectionInterface 137 */ 138 public ThreadDevice(IConnectionInterface connectionInterface) { 139 super(connectionInterface); 140 } 141 142 /* 143 * (non-Javadoc) 144 * @see com.digi.xbee.api.XBeeDevice#open() 145 */ 146 @Override 147 public void open() throws XBeeException { 148 super.open(); 149 if (xbeeProtocol != XBeeProtocol.THREAD) 150 throw new XBeeDeviceException("XBee device is not a " + getXBeeProtocol().getDescription() + 151 " device, it is a " + xbeeProtocol.getDescription() + " device."); 152 } 153 154 /* 155 * (non-Javadoc) 156 * @see com.digi.xbee.api.XBeeDevice#getXBeeProtocol() 157 */ 158 @Override 159 public XBeeProtocol getXBeeProtocol() { 160 return XBeeProtocol.THREAD; 161 } 162 163 /** 164 * Returns whether the device is associated to a network or not. 165 * 166 * @return {@code true} if the device is connected to a network, 167 * {@code false} otherwise. 168 * 169 * @throws InterfaceNotOpenException if this device connection is not open. 170 * @throws TimeoutException if there is a timeout getting the association 171 * indication status. 172 * @throws XBeeException if there is any other XBee related exception. 173 * 174 * @see #getThreadAssociationIndicationStatus() 175 * @see com.digi.xbee.api.models.ThreadAssociationIndicationStatus 176 */ 177 public boolean isConnected() throws TimeoutException, XBeeException { 178 ThreadAssociationIndicationStatus status = getThreadAssociationIndicationStatus(); 179 return status == ThreadAssociationIndicationStatus.ASSOCIATED; 180 } 181 182 /** 183 * Returns the current association status of this Thread device. 184 * 185 * @return The association indication status of the Thread device. 186 * 187 * @throws InterfaceNotOpenException if this device connection is not open. 188 * @throws TimeoutException if there is a timeout getting the association 189 * indication status. 190 * @throws XBeeException if there is any other XBee related exception. 191 * 192 * @see com.digi.xbee.api.models.ThreadAssociationIndicationStatus 193 */ 194 public ThreadAssociationIndicationStatus getThreadAssociationIndicationStatus() throws TimeoutException, 195 XBeeException { 196 byte[] associationIndicationValue = getParameter("AI"); 197 return ThreadAssociationIndicationStatus.get(ByteUtils.byteArrayToInt(associationIndicationValue)); 198 } 199 200 /** 201 * @deprecated Operation not supported in Thread protocol. This method 202 * will raise an {@link UnsupportedOperationException}. 203 */ 204 @Override 205 protected AssociationIndicationStatus getAssociationIndicationStatus() 206 throws TimeoutException, XBeeException { 207 // Not supported in Thread. 208 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 209 } 210 211 /** 212 * Sends the provided CoAP IPv6 data to the given IPv6 address and port using 213 * the specified IPv6 protocol. 214 * 215 * <p>This method blocks till a success or error response arrives or the 216 * configured receive timeout expires.</p> 217 * 218 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 219 * method and can be consulted with {@code getReceiveTimeout} method.</p> 220 * 221 * <p>For non-blocking operations use the method 222 * {@link #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, byte[])}.</p> 223 * 224 * @param ipv6Address The IPv6 address to send CoAP IPv6 data to. 225 * @param uri Uniform Resource Identifier. Every CoAP message must have a 226 * valid URI string and must meet the following criteria. There 227 * are built-in CoAP URIs: 228 * <ul> 229 * <li><b>CoAPURI.URI_DATA_TRANSMISSION:</b> "XB/TX" 230 * for data transmissions (HTTP method must be set to PUT)</li> 231 * <li><b>CoAPURI.URI_AT_COMMAND:</b> "XB/AT" for 232 * AT Command operation (HTTP method must be set to PUT or GET). 233 * After the URI, an AT command needs to be specified, for example: 234 * CoAPURI.URI_AT_COMMAND + "/NI"</li> 235 * <li><b>CoAPURI.URI_IO_SAMPLING:</b> "XB/IO" for 236 * IO operation (HTTP method must be set to POST)</li> 237 * </ul> 238 * @param method HTTP method used for the transmission. 239 * @param data Byte array containing the CoAP IPv6 data to be sent. 240 * 241 * @return A byte array containing the response, if any. Otherwise, {@code null}. 242 * 243 * @throws IllegalArgumentException if {@code uri} starts with "XB/AT" and 244 * its length is lesser than 8 (XB/AT/XX). 245 * @throws InterfaceNotOpenException if this device connection is not open. 246 * @throws NullPointerException if {@code ipv6Address == null} or 247 * if {@code uri == null} or 248 * if {@code method == null}. 249 * @throws TimeoutException if there is a timeout sending the data. 250 * @throws XBeeException if there is any other XBee related exception. 251 * 252 * @see #getReceiveTimeout() 253 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 254 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, byte[]) 255 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 256 * @see #setReceiveTimeout(int) 257 * @see com.digi.xbee.api.models.HTTPMethodEnum 258 * @see java.net.Inet6Address 259 */ 260 public byte[] sendCoAPData(Inet6Address ipv6Address, String uri, 261 HTTPMethodEnum method, byte[] data) throws TimeoutException, IllegalArgumentException, XBeeException { 262 boolean applyChanges = uri.startsWith(CoAPURI.URI_AT_COMMAND); 263 return sendCoAPData(ipv6Address, uri, method, applyChanges, data, false); 264 } 265 266 /** 267 * Sends the provided CoAP IPv6 data to the given IPv6 address and port using 268 * the specified IPv6 protocol. 269 * 270 * <p>This method blocks till a success or error response arrives or the 271 * configured receive timeout expires.</p> 272 * 273 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 274 * method and can be consulted with {@code getReceiveTimeout} method.</p> 275 * 276 * <p>For non-blocking operations use the method 277 * {@link #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, 278 * boolean, byte[])}.</p> 279 * 280 * @param ipv6Address The IPv6 address to send CoAP IPv6 data to. 281 * @param uri Uniform Resource Identifier. Every CoAP message must have a 282 * valid URI string and must meet the following criteria. There 283 * are built-in CoAP URIs: 284 * <ul> 285 * <li><b>CoAPURI.URI_DATA_TRANSMISSION:</b> "XB/TX" 286 * for data transmissions (HTTP method must be set to PUT)</li> 287 * <li><b>CoAPURI.URI_AT_COMMAND:</b> "XB/AT" for 288 * AT Command operation (HTTP method must be set to PUT or GET). 289 * After the URI, an AT command needs to be specified, for example: 290 * CoAPURI.URI_AT_COMMAND + "/NI"</li> 291 * <li><b>CoAPURI.URI_IO_SAMPLING:</b> "XB/IO" for 292 * IO operation (HTTP method must be set to POST)</li> 293 * </ul> 294 * @param method HTTP method used for the transmission. 295 * @param applyChanges {@code true} to apply the changes after sending the 296 * packet, {@code false} otherwise. 297 * @param data Byte array containing the CoAP IPv6 data to be sent. 298 * 299 * @return A byte array containing the response, if any. Otherwise, {@code null}. 300 * 301 * @throws IllegalArgumentException if {@code uri} starts with "XB/AT" and 302 * its length is lesser than 8 (XB/AT/XX). 303 * @throws InterfaceNotOpenException if this device connection is not open. 304 * @throws NullPointerException if {@code ipv6Address == null} or 305 * if {@code uri == null} or 306 * if {@code method == null}. 307 * @throws TimeoutException if there is a timeout sending the data. 308 * @throws XBeeException if there is any other XBee related exception. 309 * 310 * @see #getReceiveTimeout() 311 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, byte[]) 312 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, byte[]) 313 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 314 * @see #setReceiveTimeout(int) 315 * @see com.digi.xbee.api.models.HTTPMethodEnum 316 * @see java.net.Inet6Address 317 */ 318 public byte[] sendCoAPData(Inet6Address ipv6Address, String uri, HTTPMethodEnum method, 319 boolean applyChanges, byte[] data) throws TimeoutException, IllegalArgumentException, XBeeException { 320 return sendCoAPData(ipv6Address, uri, method, applyChanges, data, false); 321 } 322 323 /** 324 * Sends the provided CoAP IPv6 data to the given IPv6 address and port 325 * asynchronously using the specified IPv6 protocol. 326 * 327 * <p>Asynchronous transmissions do not wait for answer from the remote 328 * device or for transmit status packet.</p> 329 * 330 * <p>For blocking operations use the method 331 * {@link #sendCoAPData(Inet6Address, String, HTTPMethodEnum, byte[])}.</p> 332 * 333 * @param ipv6Address The IPv6 address to send CoAP IPv6 data to. 334 * @param uri Uniform Resource Identifier. Every CoAP message must have a 335 * valid URI string and must meet the following criteria. There 336 * are built-in CoAP URIs: 337 * <ul> 338 * <li><b>CoAPURI.URI_DATA_TRANSMISSION:</b> "XB/TX" 339 * for data transmissions (PUT)</li> 340 * <li><b>CoAPURI.URI_AT_COMMAND:</b> "XB/AT" for 341 * AT Command operation (PUT or GET). After the URI, an AT command 342 * needs to be specified, for example: 343 * CoAPURI.URI_AT_COMMAND + "/NI"</li> 344 * <li><b>CoAPURI.URI_IO_SAMPLING:</b> "XB/IO" for 345 * IO operation (POST)</li> 346 * </ul> 347 * @param method HTTP method used for the transmission. 348 * @param data Byte array containing the CoAP IPv6 data to be sent. 349 * 350 * @throws IllegalArgumentException if {@code uri} starts with "XB/AT" and 351 * its length is lesser than 8 (XB/AT/XX). 352 * @throws InterfaceNotOpenException if this device connection is not open. 353 * @throws NullPointerException if {@code ipv6Address == null} or 354 * if {@code uri == null} or 355 * if {@code method == null}. 356 * @throws TimeoutException if there is a timeout sending the data. 357 * @throws XBeeException if there is any other XBee related exception. 358 * 359 * @see #getReceiveTimeout() 360 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, byte[]) 361 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 362 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 363 * @see #setReceiveTimeout(int) 364 * @see com.digi.xbee.api.models.HTTPMethodEnum 365 * @see java.net.Inet6Address 366 */ 367 public void sendCoAPDataAsync(Inet6Address ipv6Address, String uri, 368 HTTPMethodEnum method, byte[] data) throws TimeoutException, IllegalArgumentException, XBeeException { 369 boolean applyChanges = uri.startsWith(CoAPURI.URI_AT_COMMAND); 370 sendCoAPData(ipv6Address, uri, method, applyChanges, data, true); 371 } 372 373 /** 374 * Sends the provided CoAP IPv6 data to the given IPv6 address and port 375 * asynchronously using the specified IPv6 protocol. 376 * 377 * <p>Asynchronous transmissions do not wait for answer from the remote 378 * device or for transmit status packet.</p> 379 * 380 * <p>For blocking operations use the method 381 * {@link #sendCoAPData(Inet6Address, String, HTTPMethodEnum, boolean, byte[])}.</p> 382 * 383 * @param ipv6Address The IPv6 address to send CoAP IPv6 data to. 384 * @param uri Uniform Resource Identifier. Every CoAP message must have a 385 * valid URI string and must meet the following criteria. There 386 * are built-in CoAP URIs: 387 * <ul> 388 * <li><b>CoAPURI.URI_DATA_TRANSMISSION:</b> "XB/TX" 389 * for data transmissions (PUT)</li> 390 * <li><b>CoAPURI.URI_AT_COMMAND:</b> "XB/AT" for 391 * AT Command operation (PUT or GET). After the URI, an AT command 392 * needs to be specified, for example: 393 * CoAPURI.URI_AT_COMMAND + "/NI"</li> 394 * <li><b>CoAPURI.URI_IO_SAMPLING:</b> "XB/IO" for 395 * IO operation (POST)</li> 396 * </ul> 397 * @param method HTTP method used for the transmission. 398 * @param applyChanges {@code true} to apply the changes after sending the 399 * packet, {@code false} otherwise. 400 * @param data Byte array containing the CoAP IPv6 data to be sent. 401 * 402 * @throws IllegalArgumentException if {@code uri} starts with "XB/AT" and 403 * its length is lesser than 8 (XB/AT/XX). 404 * @throws InterfaceNotOpenException if this device connection is not open. 405 * @throws NullPointerException if {@code ipv6Address == null} or 406 * if {@code uri == null} or 407 * if {@code method == null}. 408 * @throws TimeoutException if there is a timeout sending the data. 409 * @throws XBeeException if there is any other XBee related exception. 410 * 411 * @see #getReceiveTimeout() 412 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, byte[]) 413 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 414 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, byte[]) 415 * @see #setReceiveTimeout(int) 416 * @see com.digi.xbee.api.models.HTTPMethodEnum 417 * @see java.net.Inet6Address 418 */ 419 public void sendCoAPDataAsync(Inet6Address ipv6Address, String uri, HTTPMethodEnum method, 420 boolean applyChanges, byte[] data) throws TimeoutException, IllegalArgumentException, XBeeException { 421 sendCoAPData(ipv6Address, uri, method, applyChanges, data, true); 422 } 423 424 /** 425 * Sends the provided CoAP IPv6 data to the given IPv6 address and port 426 * using the specified IPv6 protocol. 427 * 428 * <p>CoAP transmissions can be performed synchronously or asynchronously. 429 * Synchronous operations block till a success or error response arrives 430 * or the configured receive timeout expires. Asynchronous transmissions 431 * do not wait for answer from the remote device or for transmit status 432 * packet.</p> 433 * 434 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 435 * method and can be consulted with {@code getReceiveTimeout} method.</p> 436 * 437 * <p>For synchronous operations use these methods:</p> 438 * <ul> 439 * <li>{@link #sendCoAPData(Inet6Address, String, HTTPMethodEnum, byte[])}.</li> 440 * <li>{@link #sendCoAPData(Inet6Address, String, HTTPMethodEnum, boolean, byte[])}.</li> 441 * </ul> 442 * <p>For asynchronous operations use these ones:</p> 443 * <ul> 444 * <li>{@link #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, byte[])}.</li> 445 * <li>{@link #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, boolean, byte[])}.</li> 446 * </ul> 447 * 448 * @param ipv6Address The IPv6 address to send CoAP IPv6 data to. 449 * @param uri Uniform Resource Identifier. Every CoAP message must have a 450 * valid URI string and must meet the following criteria. There 451 * are built-in CoAP URIs: 452 * <ul> 453 * <li><b>CoAPURI.URI_DATA_TRANSMISSION:</b> "XB/TX" 454 * for data transmissions (PUT)</li> 455 * <li><b>CoAPURI.URI_AT_COMMAND:</b> "XB/AT" for 456 * AT Command operation (PUT or GET). After the URI, an AT command 457 * needs to be specified, for example: 458 * CoAPURI.URI_AT_COMMAND + "/NI"</li> 459 * <li><b>CoAPURI.URI_IO_SAMPLING:</b> "XB/IO" for 460 * IO operation (POST)</li> 461 * </ul> 462 * @param method HTTP method used for the transmission. 463 * @param applyChanges {@code true} to apply the changes after sending the 464 * packet, {@code false} otherwise. 465 * @param data Byte array containing the CoAP IPv6 data to be sent. 466 * @param async {@code true} to make an asynchronous transmission, {@code false} 467 * to block till a success or error response arrives or the 468 * configured receive timeout expires . 469 * 470 * @return A byte array containing the response, if any. Otherwise, {@code null}. 471 * 472 * @throws IllegalArgumentException if {@code uri} starts with "XB/AT" and 473 * its length is lesser than 8 (XB/AT/XX). 474 * @throws InterfaceNotOpenException if this device connection is not open. 475 * @throws NullPointerException if {@code ipv6Address == null} or 476 * if {@code uri == null} or 477 * if {@code method == null}. 478 * @throws TimeoutException if there is a timeout sending the data. 479 * @throws XBeeException if there is any other XBee related exception. 480 * 481 * @see #getReceiveTimeout() 482 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, byte[]) 483 * @see #sendCoAPData(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 484 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, byte[]) 485 * @see #sendCoAPDataAsync(Inet6Address, String, HTTPMethodEnum, boolean, byte[]) 486 * @see #setReceiveTimeout(int) 487 * @see com.digi.xbee.api.models.HTTPMethodEnum 488 * @see java.net.Inet6Address 489 */ 490 private byte[] sendCoAPData(Inet6Address ipv6Address, String uri, HTTPMethodEnum method, 491 boolean applyChanges, byte[] data, boolean async) throws TimeoutException, IllegalArgumentException, XBeeException { 492 if (ipv6Address == null) 493 throw new NullPointerException("IPv6 address cannot be null"); 494 if (uri == null) 495 throw new NullPointerException("Uri cannot be null"); 496 if (method == null) 497 throw new NullPointerException("HTTP method cannot be null"); 498 499 // If AT command uri is used but no AT command is specified throw an error. 500 if (uri.startsWith(CoAPURI.URI_AT_COMMAND) 501 && uri.length() < CoAPURI.URI_AT_COMMAND.length() + 3) 502 throw new IllegalArgumentException("AT command URI must contain an AT command."); 503 504 // Check if device is remote. 505 if (isRemote()) 506 throw new OperationNotSupportedException("Cannot send CoAP IPv6 data from a remote device."); 507 508 if (async) 509 logger.debug(toString() + "Sending CoAP IPv6 data asynchronously to {} >> {}.", ipv6Address, 510 HexUtils.prettyHexString(data)); 511 else 512 logger.debug(toString() + "Sending CoAP IPv6 data to {} >> {}.", ipv6Address, 513 HexUtils.prettyHexString(data)); 514 515 CoAPTxRequestPacket coAPPacket = new CoAPTxRequestPacket(getNextFrameID(), 516 applyChanges ? RemoteATCommandOptions.OPTION_APPLY_CHANGES: RemoteATCommandOptions.OPTION_NONE, 517 method, ipv6Address, uri, data); 518 519 // Check for a transmit status and CoAP RX Response. 520 return sendAndCheckCoAPPacket(coAPPacket, async); 521 } 522 523 /* 524 * (non-Javadoc) 525 * @see com.digi.xbee.api.IPv6Device#sendIPData(java.net.Inet6Address, int, com.digi.xbee.api.models.IPProtocol, byte[]) 526 */ 527 @Override 528 public void sendIPData(Inet6Address ipv6Address, int destPort, 529 IPProtocol protocol, byte[] data) throws TimeoutException, 530 XBeeException { 531 if (protocol != IPProtocol.UDP && protocol != IPProtocol.COAP) 532 throw new IllegalArgumentException(ERROR_PROTOCOL_ILLEGAL); 533 super.sendIPData(ipv6Address, destPort, protocol, data); 534 } 535 536 /* 537 * (non-Javadoc) 538 * @see com.digi.xbee.api.IPv6Device#sendIPDataAsync(java.net.Inet6Address, int, com.digi.xbee.api.models.IPProtocol, byte[]) 539 */ 540 @Override 541 public void sendIPDataAsync(Inet6Address ipv6Address, int destPort, 542 IPProtocol protocol, byte[] data) throws XBeeException { 543 if (protocol != IPProtocol.UDP && protocol != IPProtocol.COAP) 544 throw new IllegalArgumentException(ERROR_PROTOCOL_ILLEGAL); 545 super.sendIPDataAsync(ipv6Address, destPort, protocol, data); 546 } 547}