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.io.ByteArrayInputStream; 019import java.net.Inet4Address; 020import java.net.UnknownHostException; 021import java.util.ArrayList; 022import java.util.List; 023 024import com.digi.xbee.api.connection.IConnectionInterface; 025import com.digi.xbee.api.connection.serial.SerialPortParameters; 026import com.digi.xbee.api.exceptions.InterfaceNotOpenException; 027import com.digi.xbee.api.exceptions.InvalidOperatingModeException; 028import com.digi.xbee.api.exceptions.TimeoutException; 029import com.digi.xbee.api.exceptions.XBeeDeviceException; 030import com.digi.xbee.api.exceptions.XBeeException; 031import com.digi.xbee.api.listeners.IPacketReceiveListener; 032import com.digi.xbee.api.models.ATCommandStatus; 033import com.digi.xbee.api.models.AccessPoint; 034import com.digi.xbee.api.models.IPAddressingMode; 035import com.digi.xbee.api.models.WiFiAssociationIndicationStatus; 036import com.digi.xbee.api.models.WiFiEncryptionType; 037import com.digi.xbee.api.models.XBeeProtocol; 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.ATCommandPacket; 042import com.digi.xbee.api.packet.common.ATCommandResponsePacket; 043import com.digi.xbee.api.utils.ByteUtils; 044 045/** 046 * This class represents a local Wi-Fi device. 047 * 048 * @see CellularDevice 049 * @see DigiPointDevice 050 * @see DigiMeshDevice 051 * @see Raw802Device 052 * @see ThreadDevice 053 * @see XBeeDevice 054 * @see ZigBeeDevice 055 * 056 * @since 1.2.0 057 */ 058public class WiFiDevice extends IPDevice { 059 060 // Constants. 061 private final static int DEFAULT_ACCESS_POINT_TIMETOUT = 15000; // 15 seconds of timeout to connect, disconnect and scan access points. 062 063 private static final String AS_COMMAND = "AS"; 064 private static final String ERROR_ALREADY_CONNECTED = "Device is already connected to an access point."; 065 066 private static final int DISCOVER_TIMEOUT = 30000; 067 068 // Variables. 069 private boolean scanningAccessPoints = false; 070 private boolean scanningAccessPointsError = false; 071 072 protected int accessPointTimeout = DEFAULT_ACCESS_POINT_TIMETOUT; 073 074 /** 075 * Class constructor. Instantiates a new {@code WiFiDevice} object in 076 * the given port name and baud rate. 077 * 078 * @param port Serial port name where Wi-Fi device is attached to. 079 * @param baudRate Serial port baud rate to communicate with the device. 080 * Other connection parameters will be set as default (8 081 * data bits, 1 stop bit, no parity, no flow control). 082 * 083 * @throws IllegalArgumentException if {@code baudRate < 0}. 084 * @throws NullPointerException if {@code port == null}. 085 * 086 * @see #WiFiDevice(IConnectionInterface) 087 * @see #WiFiDevice(String, SerialPortParameters) 088 * @see #WiFiDevice(String, int, int, int, int, int) 089 */ 090 public WiFiDevice(String port, int baudRate) { 091 this(XBee.createConnectiontionInterface(port, baudRate)); 092 } 093 094 /** 095 * Class constructor. Instantiates a new {@code WiFiDevice} object in 096 * the given serial port name and settings. 097 * 098 * @param port Serial port name where Wi-Fi 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 #WiFiDevice(IConnectionInterface) 113 * @see #WiFiDevice(String, int) 114 * @see #WiFiDevice(String, SerialPortParameters) 115 */ 116 public WiFiDevice(String port, int baudRate, int dataBits, int stopBits, int parity, int flowControl) { 117 this(port, new SerialPortParameters(baudRate, dataBits, stopBits, parity, flowControl)); 118 } 119 120 /** 121 * Class constructor. Instantiates a new {@code WiFiDevice} object in 122 * the given serial port name and parameters. 123 * 124 * @param port Serial port name where Wi-Fi device is attached to. 125 * @param serialPortParameters Object containing the serial port parameters. 126 * 127 * @throws NullPointerException if {@code port == null} or 128 * if {@code serialPortParameters == null}. 129 * 130 * @see #WiFiDevice(IConnectionInterface) 131 * @see #WiFiDevice(String, int) 132 * @see #WiFiDevice(String, int, int, int, int, int) 133 * @see com.digi.xbee.api.connection.serial.SerialPortParameters 134 */ 135 public WiFiDevice(String port, SerialPortParameters serialPortParameters) { 136 this(XBee.createConnectiontionInterface(port, serialPortParameters)); 137 } 138 139 /** 140 * Class constructor. Instantiates a new {@code WiFiDevice} object with 141 * the given connection interface. 142 * 143 * @param connectionInterface The connection interface with the physical 144 * Wi-Fi device. 145 * 146 * @throws NullPointerException if {@code connectionInterface == null} 147 * 148 * @see #WiFiDevice(String, int) 149 * @see #WiFiDevice(String, SerialPortParameters) 150 * @see #WiFiDevice(String, int, int, int, int, int) 151 * @see com.digi.xbee.api.connection.IConnectionInterface 152 */ 153 public WiFiDevice(IConnectionInterface connectionInterface) { 154 super(connectionInterface); 155 } 156 157 /* 158 * (non-Javadoc) 159 * @see com.digi.xbee.api.XBeeDevice#open() 160 */ 161 @Override 162 public void open() throws XBeeException { 163 super.open(); 164 if (xbeeProtocol != XBeeProtocol.XBEE_WIFI) 165 throw new XBeeDeviceException("XBee device is not a " + getXBeeProtocol().getDescription() + " device, it is a " + xbeeProtocol.getDescription() + " device."); 166 } 167 168 /* 169 * (non-Javadoc) 170 * @see com.digi.xbee.api.XBeeDevice#getXBeeProtocol() 171 */ 172 @Override 173 public XBeeProtocol getXBeeProtocol() { 174 return XBeeProtocol.XBEE_WIFI; 175 } 176 177 /** 178 * Returns the current association status of this Wi-Fi device. 179 * 180 * <p>It indicates occurrences of errors during the Wi-Fi transceiver 181 * initialization and connection.</p> 182 * 183 * @return The association indication status of the Wi-Fi device. 184 * 185 * @throws InterfaceNotOpenException if this device connection is not open. 186 * @throws TimeoutException if there is a timeout getting the association 187 * indication status. 188 * @throws XBeeException if there is any other XBee related exception. 189 * 190 * @see com.digi.xbee.api.models.WiFiAssociationIndicationStatus 191 */ 192 public WiFiAssociationIndicationStatus getWiFiAssociationIndicationStatus() throws TimeoutException, 193 XBeeException { 194 byte[] associationIndicationValue = getParameter("AI"); 195 return WiFiAssociationIndicationStatus.get(ByteUtils.byteArrayToInt(associationIndicationValue)); 196 } 197 198 /** 199 * Finds and reports the access point that matches the supplied SSID. 200 * 201 * <p>This method blocks until the access point is discovered or the 202 * configured access point timeout expires.</p> 203 * 204 * <p>The access point timeout is configured using the 205 * {@code setAccessPointTimeout} method and can be consulted with 206 * {@code getAccessPointTimeout} method.</p> 207 * 208 * @param ssid The SSID of the access point to discover. 209 * 210 * @return The discovered access point with the given SSID, {@code null} 211 * if the timeout expires and the access point was not found. 212 * 213 * @throws InterfaceNotOpenException if this device connection is not open. 214 * @throws NullPointerException if {@code ssid == null}. 215 * @throws TimeoutException if there is a timeout getting the access point. 216 * @throws XBeeException if there is an error sending the discovery command. 217 * 218 * @see #getAccessPointTimeout() 219 * @see #scanAccessPoints() 220 * @see #setAccessPointTimeout(int) 221 */ 222 public AccessPoint getAccessPoint(String ssid) throws XBeeException { 223 if (ssid == null) 224 throw new NullPointerException("SSID cannot be null."); 225 226 logger.debug("{}AS for '{}' access point.", toString(), ssid); 227 228 List<AccessPoint> accessPointsList = scanAccessPoints(); 229 230 for (AccessPoint accessPoint:accessPointsList) { 231 if (accessPoint.getSSID().equals(ssid)) 232 return accessPoint; 233 } 234 235 return null; 236 } 237 238 /** 239 * Performs a scan to search for access points in the vicinity. 240 * 241 * <p>This method blocks until all the access points are discovered or the 242 * configured access point timeout expires.</p> 243 * 244 * <p>The access point timeout is configured using the 245 * {@code setAccessPointTimeout} method and can be consulted with 246 * {@code getAccessPointTimeout} method.</p> 247 * 248 * @return The list of access points discovered. 249 * 250 * @throws InterfaceNotOpenException if this device connection is not open. 251 * @throws TimeoutException if there is a timeout scanning the access points. 252 * @throws XBeeException if there is any other XBee related exception. 253 * 254 * @see #getAccessPoint(String) 255 * @see #getAccessPointTimeout() 256 * @see #setAccessPointTimeout(int) 257 */ 258 public List<AccessPoint> scanAccessPoints() throws XBeeException { 259 // Check if the connection is open. 260 if (!isOpen()) 261 throw new InterfaceNotOpenException(); 262 263 final ArrayList<AccessPoint> accessPointsList = new ArrayList<AccessPoint>(); 264 265 switch (getOperatingMode()) { 266 case AT: 267 case UNKNOWN: 268 default: 269 throw new InvalidOperatingModeException(operatingMode); 270 case API: 271 case API_ESCAPE: 272 // Subscribe listener to wait for active scan responses. 273 IPacketReceiveListener packetReceiveListener = new IPacketReceiveListener() { 274 /* 275 * (non-Javadoc) 276 * @see com.digi.xbee.api.listeners.IPacketReceiveListener#packetReceived(com.digi.xbee.api.packet.XBeePacket) 277 */ 278 @Override 279 public void packetReceived(XBeePacket receivedPacket) { 280 if (!scanningAccessPoints) 281 return; 282 283 try { 284 if (((XBeeAPIPacket)receivedPacket).getFrameType() != APIFrameType.AT_COMMAND_RESPONSE) 285 return; 286 ATCommandResponsePacket response = (ATCommandResponsePacket)receivedPacket; 287 if (!response.getCommand().equals(AS_COMMAND)) 288 return; 289 290 // Check for error. 291 if (response.getStatus() == ATCommandStatus.ERROR) { 292 scanningAccessPointsError = true; 293 scanningAccessPoints = false; 294 // Check for end of discovery. 295 } else if (response.getCommandValue() == null 296 || response.getCommandValue().length == 0) 297 scanningAccessPoints = false; 298 else { 299 AccessPoint accessPoint = parseDiscoveredAccessPoint(response.getCommandValue()); 300 if (accessPoint != null) 301 accessPointsList.add(accessPoint); 302 } 303 } catch (ClassCastException e) { 304 // Do nothing here. 305 } 306 } 307 }; 308 309 logger.debug("{}Start scanning access points.", toString()); 310 addPacketListener(packetReceiveListener); 311 312 try { 313 scanningAccessPoints = true; 314 // Send the active scan command. 315 sendPacketAsync(new ATCommandPacket(getNextFrameID(), AS_COMMAND, "")); 316 317 // Wait until the discovery process finishes or timeouts. 318 long deadLine = System.currentTimeMillis() + DISCOVER_TIMEOUT; 319 while (scanningAccessPoints && System.currentTimeMillis() < deadLine) 320 sleep(100); 321 322 // Check if we exited because of a timeout. 323 if (scanningAccessPoints) 324 throw new TimeoutException(); 325 // Check if there was an error in the active scan command (device is already connected). 326 if (scanningAccessPointsError) 327 throw new XBeeException(ERROR_ALREADY_CONNECTED); 328 } finally { 329 scanningAccessPoints = false; 330 scanningAccessPointsError = false; 331 removePacketListener(packetReceiveListener); 332 logger.debug("{}Stop scanning access points.", toString()); 333 } 334 } 335 336 return accessPointsList; 337 } 338 339 /** 340 * Connects to the access point with provided SSID. 341 * 342 * <p>This method blocks until the connection with the access point is 343 * established or the configured access point timeout expires.</p> 344 * 345 * <p>The access point timeout is configured using the 346 * {@code setAccessPointTimeout} method and can be consulted with 347 * {@code getAccessPointTimeout} method.</p> 348 * 349 * <p>Once the module is connected to the access point, you can issue 350 * the {@link #writeChanges()} method to save the connection settings. This 351 * way the module will try to connect to the access point every time it 352 * is powered on.</p> 353 * 354 * @param ssid The SSID of the access point to connect to. 355 * @param password The password for the access point, {@code null} if it 356 * does not have any encryption enabled. 357 * 358 * @return {@code true} if the module connected to the access point 359 * successfully, {@code false} otherwise. 360 * 361 * @throws InterfaceNotOpenException if this device connection is not open. 362 * @throws NullPointerException if {@code ssid == null}. 363 * @throws TimeoutException if there is a timeout sending the connect 364 * commands. 365 * @throws XBeeException if the SSID provided is {@code null} or if there 366 * is any other XBee related exception. 367 * 368 * @see #connect(AccessPoint, String) 369 * @see #disconnect() 370 * @see #getAccessPoint(String) 371 * @see #getAccessPointTimeout() 372 * @see #scanAccessPoints() 373 * @see #setAccessPointTimeout(int) 374 */ 375 public boolean connect(String ssid, String password) 376 throws TimeoutException, XBeeException { 377 if (ssid == null) 378 throw new NullPointerException("SSID cannot be null."); 379 380 AccessPoint accessPoint = getAccessPoint(ssid); 381 if (accessPoint == null) 382 throw new XBeeException("Couldn't find any access point with the proviced SSID."); 383 384 return connect(accessPoint, password); 385 } 386 387 /** 388 * Connects to the provided access point. 389 * 390 * <p>This method blocks until the connection with the access point is 391 * established or the configured access point timeout expires.</p> 392 * 393 * <p>The access point timeout is configured using the 394 * {@code setAccessPointTimeout} method and can be consulted with 395 * {@code getAccessPointTimeout} method.</p> 396 * 397 * <p>Once the module is connected to the access point, you can issue 398 * the {@code writeSettings} method to save the connection settings. This 399 * way the module will try to connect to the access point every time it 400 * is powered on.</p> 401 * 402 * @param accessPoint The access point to connect to. 403 * @param password The password for the access point, {@code null} if it 404 * does not have any encryption enabled. 405 * 406 * @return {@code true} if the module connected to the access point 407 * successfully, {@code false} otherwise. 408 * 409 * @throws InterfaceNotOpenException if this device connection is not open. 410 * @throws NullPointerException if {@code accessPoint == null}. 411 * @throws TimeoutException if there is a timeout sending the connect 412 * commands. 413 * @throws XBeeException if there is any other XBee related exception. 414 * 415 * @see #connect(String, String) 416 * @see #disconnect() 417 * @see #getAccessPoint(String) 418 * @see #getAccessPointTimeout() 419 * @see #scanAccessPoints() 420 * @see #setAccessPointTimeout(int) 421 * @see com.digi.xbee.api.models.AccessPoint 422 */ 423 public boolean connect(AccessPoint accessPoint, String password) 424 throws TimeoutException, XBeeException { 425 if (accessPoint == null) 426 throw new NullPointerException("Access point cannot be null."); 427 428 // Set connection parameters. 429 setParameter("ID", accessPoint.getSSID().getBytes()); 430 setParameter("EE", new byte[]{(byte)accessPoint.getEncryptionType().getID()}); 431 if (password != null && accessPoint.getEncryptionType() != WiFiEncryptionType.NONE) 432 setParameter("PK", password.getBytes()); 433 434 // Wait for the module to connect to the access point. 435 long deadLine = System.currentTimeMillis() + accessPointTimeout; 436 while (System.currentTimeMillis() < deadLine) { 437 sleep(100); 438 // Get the association indication value of the module. 439 byte[] status = getParameter("AI"); 440 if (status == null || status.length < 1) 441 continue; 442 if (status[0] == 0) 443 return true; 444 } 445 446 return false; 447 } 448 449 /** 450 * Disconnects from the access point the device is connected to. 451 * 452 * <p>This method blocks until the device disconnects totally from the 453 * access point or the configured access point timeout expires.</p> 454 * 455 * <p>The access point timeout is configured using the 456 * {@code setAccessPointTimeout} method and can be consulted with 457 * {@code getAccessPointTimeout} method.</p> 458 * 459 * @return {@code true} if the module disconnected from the access point 460 * successfully, {@code false} otherwise. 461 * 462 * @throws InterfaceNotOpenException if this device connection is not open. 463 * @throws TimeoutException if there is a timeout sending the disconnect 464 * command. 465 * @throws XBeeException if there is any other XBee related exception. 466 * 467 * @see #connect(AccessPoint, String) 468 * @see #connect(String, String) 469 * @see #getAccessPointTimeout() 470 * @see #setAccessPointTimeout(int) 471 */ 472 public boolean disconnect() throws TimeoutException, XBeeException { 473 executeParameter("NR"); 474 // Wait for the module to connect to the access point. 475 long deadLine = System.currentTimeMillis() + accessPointTimeout; 476 while (System.currentTimeMillis() < deadLine) { 477 sleep(100); 478 // Get the association indication value of the module. 479 byte[] status = getParameter("AI"); 480 if (status == null || status.length < 1) 481 continue; 482 // Status 0x23 (35) means the SSID is not configured. 483 if (status[0] == 0x23) 484 return true; 485 } 486 487 return false; 488 } 489 490 /** 491 * Returns whether the device is connected to an access point or not. 492 * 493 * @return {@code true} if the device is connected to an access point, 494 * {@code false} otherwise. 495 * 496 * @throws InterfaceNotOpenException if this device connection is not open. 497 * @throws TimeoutException if there is a timeout getting the association 498 * indication status. 499 * @throws XBeeException if there is any other XBee related exception. 500 * 501 * @see #getWiFiAssociationIndicationStatus() 502 * @see com.digi.xbee.api.models.WiFiAssociationIndicationStatus 503 */ 504 public boolean isConnected() throws TimeoutException, XBeeException { 505 WiFiAssociationIndicationStatus status = getWiFiAssociationIndicationStatus(); 506 507 return status == WiFiAssociationIndicationStatus.SUCCESSFULLY_JOINED; 508 } 509 510 /** 511 * Parses the given active scan API data and returns an {@code AccessPoint} 512 * object. 513 * 514 * @param data Data to parse. 515 * 516 * @return Discovered access point. {@code null} if the parsed data does 517 * not correspond to an access point. 518 */ 519 private AccessPoint parseDiscoveredAccessPoint(byte[] data) { 520 AccessPoint accessPoint = null; 521 522 int version; 523 int channel; 524 int security; 525 int signalStrength; 526 int signalQuality; 527 528 String ssidName = ""; 529 530 ByteArrayInputStream inputStream = new ByteArrayInputStream(data); 531 if (inputStream.available() == 0) 532 return null; 533 // Read the version. 534 version = ByteUtils.byteArrayToInt((ByteUtils.readBytes(1, inputStream))); 535 if (inputStream.available() == 0) 536 return null; 537 // Read the channel. 538 channel = ByteUtils.byteArrayToInt((ByteUtils.readBytes(1, inputStream))); 539 if (inputStream.available() == 0) 540 return null; 541 // Read the encryption type. 542 security = ByteUtils.byteArrayToInt((ByteUtils.readBytes(1, inputStream))); 543 if (inputStream.available() == 0) 544 return null; 545 // Read the signal strength and generate the signal quality. 546 signalStrength = ByteUtils.byteArrayToInt((ByteUtils.readBytes(1, inputStream))); 547 signalQuality = getSignalQuality(version, signalStrength); 548 549 // Read the SSID name. 550 if (inputStream.available() == 0) 551 return null; 552 int readByte = -1; 553 while ((readByte = inputStream.read()) != -1) 554 ssidName += new String(new byte[]{(byte)(readByte & 0xFF)}); 555 556 // Build the access point object. 557 accessPoint = new AccessPoint(ssidName, WiFiEncryptionType.get(security), channel, signalQuality); 558 559 logger.debug("{}Discovered: SSID[{}], encryption[{}], channel[{}], signal quality[{}].", 560 toString(), ssidName, WiFiEncryptionType.get(security).name(), channel, signalQuality); 561 562 return accessPoint; 563 } 564 565 /** 566 * Converts the signal strength value in signal quality (%) based on the 567 * provided Wi-Fi version. 568 * 569 * @param wifiVersion Wi-Fi protocol version of the Wi-Fi XBee device. 570 * @param signalStrength Signal strength value to convert to %. 571 * 572 * @return The signal quality in %. 573 */ 574 private int getSignalQuality(int wifiVersion, int signalStrength) { 575 int quality; 576 577 if (wifiVersion == 1) { 578 if (signalStrength <= -100) 579 quality = 0; 580 else if(signalStrength >= -50) 581 quality = 100; 582 else 583 quality = (2 * (signalStrength + 100)); 584 } else 585 quality = 2 * signalStrength; 586 587 if (quality > 100) 588 quality = 100; 589 if (quality < 0) 590 quality = 0; 591 592 return quality; 593 } 594 595 /** 596 * Sleeps the thread for the given number of milliseconds. 597 * 598 * @param milliseconds The number of milliseconds that the thread should 599 * be sleeping. 600 */ 601 private void sleep(int milliseconds) { 602 try { 603 Thread.sleep(milliseconds); 604 } catch (InterruptedException e) { } 605 } 606 607 /** 608 * Returns the configured access point timeout for connecting, 609 * disconnecting and scanning access points. 610 * 611 * @return The current access point timeout in milliseconds. 612 * 613 * @see #setAccessPointTimeout(int) 614 */ 615 public int getAccessPointTimeout() { 616 return accessPointTimeout; 617 } 618 619 /** 620 * Configures the access point timeout in milliseconds for connecting, 621 * disconnecting and scanning access points. 622 * 623 * @param accessPointTimeout The new access point timeout in milliseconds. 624 * 625 * @throws IllegalArgumentException if {@code accessPointTimeout < 0}. 626 * 627 * @see #getAccessPointTimeout() 628 */ 629 public void setAccessPointTimeout(int accessPointTimeout) { 630 if (accessPointTimeout < 0) 631 throw new IllegalArgumentException("Access point timeout cannot be less than 0."); 632 633 this.accessPointTimeout = accessPointTimeout; 634 } 635 636 /** 637 * Sets the IP addressing mode. 638 * 639 * @param mode IP addressing mode. 640 * 641 * @throws NullPointerException if {@code mode == null}. 642 * @throws TimeoutException if there is a timeout setting the IP addressing 643 * mode. 644 * @throws XBeeException if there is any other XBee related exception. 645 * 646 * @see #getIPAddressingMode() 647 * @see IPAddressingMode 648 */ 649 public void setIPAddressingMode(IPAddressingMode mode) throws TimeoutException, XBeeException { 650 if (mode == null) 651 throw new NullPointerException("IP addressing mode cannot be null."); 652 653 setParameter("MA", ByteUtils.intToByteArray(mode.getID())); 654 } 655 656 /** 657 * Returns the IP addressing mode. 658 * 659 * @return The configured IP addressing mode. 660 * 661 * @throws TimeoutException if there is a timeout reading the IP addressing 662 * mode. 663 * @throws XBeeException if there is any other XBee related exception. 664 * 665 * @see #setIPAddressingMode(IPAddressingMode) 666 * @see IPAddressingMode 667 */ 668 public IPAddressingMode getIPAddressingMode() throws TimeoutException, XBeeException { 669 return IPAddressingMode.get(ByteUtils.byteArrayToInt(getParameter("MA"))); 670 } 671 672 /** 673 * Sets the IP address of the module. 674 * 675 * <p>This method <b>can only be called</b> if the module is configured in 676 * {@link IPAddressingMode#STATIC} mode. Otherwise an {@code XBeeException} 677 * will be thrown.</p> 678 * 679 * @param address IP address. 680 * 681 * @throws NullPointerException if {@code address == null}. 682 * @throws TimeoutException if there is a timeout setting the IP address. 683 * @throws XBeeException if the module is in {@link IPAddressingMode#DHCP} 684 * mode or there is any other XBee related exception. 685 * 686 * @see #getIPAddress() 687 * @see #getIPAddressingMode() 688 * @see Inet4Address 689 */ 690 public void setIPAddress(Inet4Address address) throws TimeoutException, XBeeException { 691 if (address == null) 692 throw new NullPointerException("IP address cannot be null."); 693 694 setParameter("MY", address.getAddress()); 695 } 696 697 /** 698 * Sets the IP address subnet mask. 699 * 700 * <p>This method <b>can only be called</b> if the module is configured in 701 * {@link IPAddressingMode#STATIC} mode. Otherwise an {@code XBeeException} 702 * will be thrown.</p> 703 * 704 * @param address IP address subnet mask. 705 * 706 * @throws NullPointerException if {@code address == null}. 707 * @throws TimeoutException if there is a timeout setting the IP address 708 * mask. 709 * @throws XBeeException if the module is in {@link IPAddressingMode#DHCP} 710 * mode or there is any other XBee related exception. 711 * 712 * @see #getIPAddressingMode() 713 * @see #getIPAddressMask() 714 * @see Inet4Address 715 */ 716 public void setIPAddressMask(Inet4Address address) throws TimeoutException, XBeeException { 717 if (address == null) 718 throw new NullPointerException("Address mask cannot be null."); 719 720 setParameter("MK", address.getAddress()); 721 } 722 723 /** 724 * Returns the IP address subnet mask. 725 * 726 * @return The configured IP address subnet mask. 727 * 728 * @throws TimeoutException if there is a timeout reading the IP address 729 * mask. 730 * @throws XBeeException if there is any other XBee related exception. 731 * 732 * @see #setIPAddressMask(Inet4Address) 733 * @see Inet4Address 734 */ 735 public Inet4Address getIPAddressMask() throws TimeoutException, XBeeException { 736 try { 737 return (Inet4Address) Inet4Address.getByAddress(getParameter("MK")); 738 } catch (UnknownHostException e) { 739 throw new XBeeException(e); 740 } 741 } 742 743 /** 744 * Sets the IP address of the gateway. 745 * 746 * <p>This method <b>can only be called</b> if the module is configured in 747 * {@link IPAddressingMode#STATIC} mode. Otherwise an {@code XBeeException} 748 * will be thrown.</p> 749 * 750 * @param address IP address of the gateway. 751 * 752 * @throws NullPointerException if {@code address == null}. 753 * @throws TimeoutException if there is a timeout setting the gateway IP 754 * address. 755 * @throws XBeeException if the module is in {@link IPAddressingMode#DHCP} 756 * mode or there is any other XBee related exception. 757 * 758 * @see #getGatewayIPAddress() 759 * @see #getIPAddressingMode() 760 * @see Inet4Address 761 */ 762 public void setGatewayIPAddress(Inet4Address address) throws TimeoutException, XBeeException { 763 if (address == null) 764 throw new NullPointerException("Gateway address cannot be null."); 765 766 setParameter("GW", address.getAddress()); 767 } 768 769 /** 770 * Returns the IP address of the gateway. 771 * 772 * @return The configured IP address of the gateway. 773 * 774 * @throws TimeoutException if there is a timeout reading the gateway IP 775 * address. 776 * @throws XBeeException if there is any other XBee related exception. 777 * 778 * @see #setGatewayIPAddress(Inet4Address) 779 * @see Inet4Address 780 */ 781 public Inet4Address getGatewayIPAddress() throws TimeoutException, XBeeException { 782 try { 783 return (Inet4Address) Inet4Address.getByAddress(getParameter("GW")); 784 } catch (UnknownHostException e) { 785 throw new XBeeException(e); 786 } 787 } 788 789 /** 790 * Sets the IP address of domain name server. 791 * 792 * @param address DNS address. 793 * 794 * @throws NullPointerException if {@code address == null}. 795 * @throws TimeoutException if there is a timeout setting the DNS address. 796 * @throws XBeeException if there is any other XBee related exception. 797 * 798 * @see #getDNSAddress() 799 * @see Inet4Address 800 */ 801 public void setDNSAddress(Inet4Address address) throws TimeoutException, XBeeException { 802 if (address == null) 803 throw new NullPointerException("DNS address cannot be null."); 804 805 setParameter("NS", address.getAddress()); 806 } 807 808 /** 809 * Returns the IP address of domain name server. 810 * 811 * @return The configured DNS address. 812 * 813 * @throws TimeoutException if there is a timeout reading the DNS address. 814 * @throws XBeeException if there is any other XBee related exception. 815 * 816 * @see #setDNSAddress(Inet4Address) 817 * @see Inet4Address 818 */ 819 public Inet4Address getDNSAddress() throws TimeoutException, XBeeException { 820 try { 821 return (Inet4Address) Inet4Address.getByAddress(getParameter("NS")); 822 } catch (UnknownHostException e) { 823 throw new XBeeException(e); 824 } 825 } 826 827}