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.util.Set; 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.io.IOLine; 028import com.digi.xbee.api.listeners.IIOSampleReceiveListener; 029import com.digi.xbee.api.listeners.ISMSReceiveListener; 030import com.digi.xbee.api.models.AssociationIndicationStatus; 031import com.digi.xbee.api.models.CellularAssociationIndicationStatus; 032import com.digi.xbee.api.models.PowerLevel; 033import com.digi.xbee.api.models.XBee64BitAddress; 034import com.digi.xbee.api.models.XBeeIMEIAddress; 035import com.digi.xbee.api.models.XBeeProtocol; 036import com.digi.xbee.api.packet.XBeePacket; 037import com.digi.xbee.api.packet.cellular.TXSMSPacket; 038import com.digi.xbee.api.utils.ByteUtils; 039 040/** 041 * This class represents a local Cellular device. 042 * 043 * @see DigiPointDevice 044 * @see DigiMeshDevice 045 * @see Raw802Device 046 * @see ThreadDevice 047 * @see WiFiDevice 048 * @see XBeeDevice 049 * @see ZigBeeDevice 050 * 051 * @since 1.2.0 052 */ 053public class CellularDevice extends IPDevice { 054 055 // Constants 056 private static final String OPERATION_EXCEPTION = "Operation not supported in Cellular protocol."; 057 058 // Variables 059 private XBeeIMEIAddress imeiAddress; 060 061 /** 062 * Class constructor. Instantiates a new {@code CellularDevice} object in 063 * the given port name and baud rate. 064 * 065 * @param port Serial port name where Cellular device is attached to. 066 * @param baudRate Serial port baud rate to communicate with the device. 067 * Other connection parameters will be set as default (8 068 * data bits, 1 stop bit, no parity, no flow control). 069 * 070 * @throws IllegalArgumentException if {@code baudRate < 0}. 071 * @throws NullPointerException if {@code port == null}. 072 * 073 * @see #CellularDevice(IConnectionInterface) 074 * @see #CellularDevice(String, SerialPortParameters) 075 * @see #CellularDevice(String, int, int, int, int, int) 076 */ 077 public CellularDevice(String port, int baudRate) { 078 this(XBee.createConnectiontionInterface(port, baudRate)); 079 } 080 081 /** 082 * Class constructor. Instantiates a new {@code CellularDevice} object in 083 * the given serial port name and settings. 084 * 085 * @param port Serial port name where Cellular device is attached to. 086 * @param baudRate Serial port baud rate to communicate with the device. 087 * @param dataBits Serial port data bits. 088 * @param stopBits Serial port data bits. 089 * @param parity Serial port data bits. 090 * @param flowControl Serial port data bits. 091 * 092 * @throws IllegalArgumentException if {@code baudRate < 0} or 093 * if {@code dataBits < 0} or 094 * if {@code stopBits < 0} or 095 * if {@code parity < 0} or 096 * if {@code flowControl < 0}. 097 * @throws NullPointerException if {@code port == null}. 098 * 099 * @see #CellularDevice(IConnectionInterface) 100 * @see #CellularDevice(String, int) 101 * @see #CellularDevice(String, SerialPortParameters) 102 */ 103 public CellularDevice(String port, int baudRate, int dataBits, int stopBits, int parity, int flowControl) { 104 this(port, new SerialPortParameters(baudRate, dataBits, stopBits, parity, flowControl)); 105 } 106 107 /** 108 * Class constructor. Instantiates a new {@code CellularDevice} object in 109 * the given serial port name and parameters. 110 * 111 * @param port Serial port name where Cellular device is attached to. 112 * @param serialPortParameters Object containing the serial port parameters. 113 * 114 * @throws NullPointerException if {@code port == null} or 115 * if {@code serialPortParameters == null}. 116 * 117 * @see #CellularDevice(IConnectionInterface) 118 * @see #CellularDevice(String, int) 119 * @see #CellularDevice(String, int, int, int, int, int) 120 * @see com.digi.xbee.api.connection.serial.SerialPortParameters 121 */ 122 public CellularDevice(String port, SerialPortParameters serialPortParameters) { 123 this(XBee.createConnectiontionInterface(port, serialPortParameters)); 124 } 125 126 /** 127 * Class constructor. Instantiates a new {@code CellularDevice} object with 128 * the given connection interface. 129 * 130 * @param connectionInterface The connection interface with the physical 131 * Cellular device. 132 * 133 * @throws NullPointerException if {@code connectionInterface == null} 134 * 135 * @see #CellularDevice(String, int) 136 * @see #CellularDevice(String, SerialPortParameters) 137 * @see #CellularDevice(String, int, int, int, int, int) 138 * @see com.digi.xbee.api.connection.IConnectionInterface 139 */ 140 public CellularDevice(IConnectionInterface connectionInterface) { 141 super(connectionInterface); 142 } 143 144 /* 145 * (non-Javadoc) 146 * @see com.digi.xbee.api.XBeeDevice#open() 147 */ 148 @Override 149 public void open() throws XBeeException { 150 super.open(); 151 if (xbeeProtocol != XBeeProtocol.CELLULAR) 152 throw new XBeeDeviceException("XBee device is not a " + getXBeeProtocol().getDescription() + " device, it is a " + xbeeProtocol.getDescription() + " device."); 153 } 154 155 /* 156 * (non-Javadoc) 157 * @see com.digi.xbee.api.XBeeDevice#getXBeeProtocol() 158 */ 159 @Override 160 public XBeeProtocol getXBeeProtocol() { 161 return XBeeProtocol.CELLULAR; 162 } 163 164 /* 165 * (non-Javadoc) 166 * @see com.digi.xbee.api.AbstractXBeeDevice#readDeviceInfo() 167 */ 168 @Override 169 public void readDeviceInfo() throws TimeoutException, XBeeException { 170 super.readDeviceInfo(); 171 172 // Generate the IMEI address. 173 imeiAddress = new XBeeIMEIAddress(xbee64BitAddress.getValue()); 174 } 175 176 /** 177 * Returns whether the device is connected to the Internet or not. 178 * 179 * @return {@code true} if the device is connected to the Internet, 180 * {@code false} otherwise. 181 * 182 * @throws InterfaceNotOpenException if this device connection is not open. 183 * @throws TimeoutException if there is a timeout getting the association 184 * indication status. 185 * @throws XBeeException if there is any other XBee related exception. 186 * 187 * @see #getCellularAssociationIndicationStatus() 188 * @see com.digi.xbee.api.models.CellularAssociationIndicationStatus 189 */ 190 public boolean isConnected() throws TimeoutException, XBeeException { 191 CellularAssociationIndicationStatus status = getCellularAssociationIndicationStatus(); 192 return status == CellularAssociationIndicationStatus.SUCCESSFULLY_CONNECTED; 193 } 194 195 /** 196 * Returns the IMEI address of this Cellular device. 197 * 198 * <p>To refresh this value use the {@link #readDeviceInfo()} method.</p> 199 * 200 * @return The IMEI address of this Cellular device. 201 * 202 * @see com.digi.xbee.api.models.XBeeIMEIAddress 203 */ 204 public XBeeIMEIAddress getIMEIAddress() { 205 return imeiAddress; 206 } 207 208 /** 209 * Returns the current association status of this Cellular device. 210 * 211 * <p>It indicates occurrences of errors during the modem initialization 212 * and connection.</p> 213 * 214 * @return The association indication status of the Cellular device. 215 * 216 * @throws InterfaceNotOpenException if this device connection is not open. 217 * @throws TimeoutException if there is a timeout getting the association 218 * indication status. 219 * @throws XBeeException if there is any other XBee related exception. 220 * 221 * @see com.digi.xbee.api.models.CellularAssociationIndicationStatus 222 */ 223 public CellularAssociationIndicationStatus getCellularAssociationIndicationStatus() throws TimeoutException, 224 XBeeException { 225 byte[] associationIndicationValue = getParameter("AI"); 226 return CellularAssociationIndicationStatus.get(ByteUtils.byteArrayToInt(associationIndicationValue)); 227 } 228 229 /** 230 * @deprecated Operation not supported in Cellular protocol. Use 231 * {@link #getCellularAssociationIndicationStatus()} instead. 232 * This method will raise an 233 * {@link UnsupportedOperationException}. 234 */ 235 @Override 236 protected AssociationIndicationStatus getAssociationIndicationStatus() 237 throws TimeoutException, XBeeException { 238 // Not supported in Cellular. 239 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 240 } 241 242 /** 243 * @deprecated Cellular protocol does not have an associated 64-bit address. 244 */ 245 @Override 246 public XBee64BitAddress get64BitAddress() { 247 // Cellular protocol does not have 64-bit address. 248 return null; 249 } 250 251 /** 252 * @deprecated Operation not supported in this protocol. This method will 253 * raise an {@link UnsupportedOperationException}. 254 */ 255 @Override 256 public void addIOSampleListener(IIOSampleReceiveListener listener) { 257 // Not supported in IP modules. 258 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 259 } 260 261 /** 262 * @deprecated Operation not supported in this protocol. This method will 263 * raise an {@link UnsupportedOperationException}. 264 */ 265 @Override 266 public void removeIOSampleListener(IIOSampleReceiveListener listener) { 267 // Not supported in IP modules. 268 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 269 } 270 271 /** 272 * @deprecated Operation not supported in Cellular protocol. This method 273 * will raise an {@link UnsupportedOperationException}. 274 */ 275 @Override 276 public Set<IOLine> getDIOChangeDetection() throws TimeoutException, 277 XBeeException { 278 // Not supported in Cellular. 279 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 280 } 281 282 /** 283 * @deprecated Operation not supported in Cellular protocol. This method 284 * will raise an {@link UnsupportedOperationException}. 285 */ 286 @Override 287 public void setDIOChangeDetection(Set<IOLine> lines) 288 throws TimeoutException, XBeeException { 289 // Not supported in Cellular. 290 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 291 } 292 293 /** 294 * @deprecated Operation not supported in Cellular protocol. This method 295 * will raise an {@link UnsupportedOperationException}. 296 */ 297 @Override 298 public int getIOSamplingRate() throws TimeoutException, XBeeException { 299 // Not supported in Cellular. 300 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 301 } 302 303 /** 304 * @deprecated Operation not supported in Cellular protocol. This method 305 * will raise an {@link UnsupportedOperationException}. 306 */ 307 @Override 308 public void setIOSamplingRate(int rate) throws TimeoutException, 309 XBeeException { 310 // Not supported in Cellular. 311 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 312 } 313 314 /** 315 * @deprecated Cellular protocol does not have node identifier. 316 */ 317 @Override 318 public String getNodeID() { 319 // Cellular protocol does not have Node Identifier. 320 return null; 321 } 322 323 /** 324 * @deprecated Operation not supported in Cellular protocol. This method 325 * will raise an {@link UnsupportedOperationException}. 326 */ 327 @Override 328 public void setNodeID(String nodeID) throws TimeoutException, XBeeException { 329 // Not supported in Cellular. 330 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 331 } 332 333 /** 334 * @deprecated Operation not supported in Cellular protocol. This method 335 * will raise an {@link UnsupportedOperationException}. 336 */ 337 @Override 338 public PowerLevel getPowerLevel() throws TimeoutException, XBeeException { 339 // Not supported in Cellular. 340 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 341 } 342 343 /** 344 * @deprecated Operation not supported in Cellular protocol. This method 345 * will raise an {@link UnsupportedOperationException}. 346 */ 347 @Override 348 public void setPowerLevel(PowerLevel powerLevel) throws TimeoutException, 349 XBeeException { 350 // Not supported in Cellular. 351 throw new UnsupportedOperationException(OPERATION_EXCEPTION); 352 } 353 354 /* 355 * (non-Javadoc) 356 * @see com.digi.xbee.api.AbstractXBeeDevice#addSMSListener(com.digi.xbee.api.listeners.ISMSReceiveListener) 357 */ 358 @Override 359 public void addSMSListener(ISMSReceiveListener listener) { 360 super.addSMSListener(listener); 361 } 362 363 /* 364 * (non-Javadoc) 365 * @see com.digi.xbee.api.AbstractXBeeDevice#removeSMSListener(com.digi.xbee.api.listeners.ISMSReceiveListener) 366 */ 367 @Override 368 public void removeSMSListener(ISMSReceiveListener listener) { 369 super.removeSMSListener(listener); 370 } 371 372 /** 373 * Sends the provided SMS message to the given phone number. 374 * 375 * <p>This method blocks till a success or error response arrives or the 376 * configured receive timeout expires.</p> 377 * 378 * <p>The receive timeout is configured using the {@code setReceiveTimeout} 379 * method and can be consulted with {@code getReceiveTimeout} method.</p> 380 * 381 * <p>For non-blocking operations use the method 382 * {@link #sendSMSAsync(String, String)}.</p> 383 * 384 * @param phoneNumber The phone number to send the SMS to. 385 * @param data String containing the text of the SMS. 386 * 387 * @throws IllegalArgumentException if {@code phoneNumber.length() > 20} or 388 * if {@code phoneNumber} is invalid. 389 * @throws InterfaceNotOpenException if this device connection is not open. 390 * @throws NullPointerException if {@code phoneNumber == null} or 391 * if {@code data == null}. 392 * @throws TimeoutException if there is a timeout sending the SMS. 393 * @throws XBeeException if there is any other XBee related exception. 394 * 395 * @see #getReceiveTimeout() 396 * @see #setReceiveTimeout(int) 397 * @see #sendSMSAsync(String, String) 398 */ 399 public void sendSMS(String phoneNumber, String data) throws TimeoutException, XBeeException { 400 if (phoneNumber == null) 401 throw new NullPointerException("Phone number cannot be null"); 402 if (data == null) 403 throw new NullPointerException("Data cannot be null"); 404 405 // Check if device is remote. 406 if (isRemote()) 407 throw new OperationNotSupportedException("Cannot send SMS from a remote device."); 408 409 logger.debug(toString() + "Sending SMS to {} >> {}.", phoneNumber, data); 410 411 XBeePacket xbeePacket = new TXSMSPacket(getNextFrameID(), phoneNumber, data); 412 413 sendAndCheckXBeePacket(xbeePacket, false); 414 } 415 416 /** 417 * Sends asynchronously the provided SMS to the given phone number. 418 * 419 * <p>Asynchronous transmissions do not wait for answer or for transmit 420 * status packet.</p> 421 * 422 * @param phoneNumber The phone number to send the SMS to. 423 * @param data String containing the text of the SMS. 424 * 425 * @throws IllegalArgumentException if {@code phoneNumber.length() > 20} or 426 * if {@code phoneNumber} is invalid. 427 * @throws InterfaceNotOpenException if this device connection is not open. 428 * @throws NullPointerException if {@code phoneNumber == null} or 429 * if {@code data == null}. 430 * @throws TimeoutException if there is a timeout sending the SMS. 431 * @throws XBeeException if there is any other XBee related exception. 432 * 433 * @see #sendSMS(String, String) 434 */ 435 public void sendSMSAsync(String phoneNumber, String data) throws TimeoutException, XBeeException { 436 if (phoneNumber == null) 437 throw new NullPointerException("Phone number cannot be null"); 438 if (data == null) 439 throw new NullPointerException("Data cannot be null"); 440 441 // Check if device is remote. 442 if (isRemote()) 443 throw new OperationNotSupportedException("Cannot send SMS from a remote device."); 444 445 logger.debug(toString() + "Sending SMS asynchronously to {} >> {}.", phoneNumber, data); 446 447 XBeePacket xbeePacket = new TXSMSPacket(getNextFrameID(), phoneNumber, data); 448 449 sendAndCheckXBeePacket(xbeePacket, true); 450 } 451}