/**
		 * Sends the given AT command and waits for answer or until the configured 
		 * receive timeout expires.
		 * 
		 * <p>The receive timeout is configured using the {@code setReceiveTimeout}
		 * method and can be consulted with {@code getReceiveTimeout} method.</p>
		 * 
		 * @param command AT command to be sent.
		 * @return An {@code ATCommandResponse} object containing the response of 
		 *         the command or {@code null} if there is no response.
		 *         
		 * @throws InterfaceNotOpenException if this device connection is not open.
		 * @throws InvalidOperatingModeException if the operating mode is different 
		 *                                       than {@link OperatingMode#API} and 
		 *                                       {@link OperatingMode#API_ESCAPE}.
		 * @throws IOException if an I/O error occurs while sending the AT command.
		 * @throws ArgumentNullException if {@code command == null}.
		 * @throws TimeoutException if the configured time expires while waiting 
		 *                          for the command reply.
		 * 
		 * @see XBeeDevice#getReceiveTimeout()
		 * @see XBeeDevice#setReceiveTimeout(int)
		 * @see com.digi.xbee.api.models.ATCommand
		 * @see com.digi.xbee.api.models.ATCommandResponse
		 */
		protected ATCommandResponse SendATCommand(ATCommand command)
		/*throws InvalidOperatingModeException, TimeoutException, IOException*/ {
			// Check if command is null.
			if (command == null)
				throw new ArgumentNullException("AT command cannot be null.");
			// Check connection.
			if (!connectionInterface.SerialPort.IsOpen)
				throw new InterfaceNotOpenException();

			ATCommandResponse response = null;
			OperatingMode operatingMode = GetOperatingMode();
			switch (operatingMode)
			{
				case OperatingMode.AT:
				case OperatingMode.UNKNOWN:
				default:
					throw new InvalidOperatingModeException(operatingMode);
				case OperatingMode.API:
				case OperatingMode.API_ESCAPE:
					// Create the corresponding AT command packet depending on if the device is local or remote.
					XBeePacket packet;
					if (IsRemote)
					{
						XBee16BitAddress remote16BitAddress = Get16BitAddress();
						if (remote16BitAddress == null)
							remote16BitAddress = XBee16BitAddress.UNKNOWN_ADDRESS;
						RemoteATCommandOptions remoteATCommandOptions = RemoteATCommandOptions.OPTION_NONE;
						if (IsApplyConfigurationChangesEnabled())
							remoteATCommandOptions |= RemoteATCommandOptions.OPTION_APPLY_CHANGES;
						packet = new RemoteATCommandPacket(GetNextFrameID(), Get64BitAddress(), remote16BitAddress, (byte)remoteATCommandOptions, command.Command, command.Parameter);
					}
					else
					{
						if (IsApplyConfigurationChangesEnabled())
							packet = new ATCommandPacket(GetNextFrameID(), command.Command, command.Parameter);
						else
							packet = new ATCommandQueuePacket(GetNextFrameID(), command.Command, command.Parameter);
					}
					if (command.Parameter == null)
						logger.DebugFormat(ToString() + "Sending AT command '{0}'.", command.Command);
					else
						logger.DebugFormat(ToString() + "Sending AT command '{0} {1}'.", command.Command, HexUtils.PrettyHexString(command.Parameter));
					try
					{
						// Send the packet and build the corresponding response depending on if the device is local or remote.
						XBeePacket answerPacket;
						if (IsRemote)
							answerPacket = localXBeeDevice.SendXBeePacket(packet);
						else
							answerPacket = SendXBeePacket(packet);
						if (answerPacket is ATCommandResponsePacket)
							response = new ATCommandResponse(command, ((ATCommandResponsePacket)answerPacket).CommandValue, ((ATCommandResponsePacket)answerPacket).Status);
						else if (answerPacket is RemoteATCommandResponsePacket)
							response = new ATCommandResponse(command, ((RemoteATCommandResponsePacket)answerPacket).getCommandValue(), ((RemoteATCommandResponsePacket)answerPacket).Status);

						if (response != null && response.Response != null)
							logger.DebugFormat(ToString() + "AT command response: {0}.", HexUtils.PrettyHexString(response.Response));
						else
							logger.Debug(ToString() + "AT command response: null.");
					}
					catch (InvalidCastException e)
					{
						logger.Error("Received an invalid packet type after sending an AT command packet." + e);
					}
					break;
			}
			return response;
		}
		/**
		 * Checks if the provided {@code ATCommandResponse} is valid throwing an 
		 * {@code ATCommandException} in case it is not.
		 * 
		 * @param response The {@code ATCommandResponse} to check.
		 * 
		 * @throws ATCommandException if {@code response == null} or 
		 *                            if {@code response.getResponseStatus() != ATCommandStatus.OK}.
		 * 
		 * @see com.digi.xbee.api.models.ATCommandResponse
		 */
		protected void CheckATCommandResponseIsValid(ATCommandResponse response)/*throws ATCommandException */{
			if (response == null || response.Status == null)
				throw new ATCommandException(ATCommandStatus.UNKNOWN);
			else if (response.Status != ATCommandStatus.OK)
				throw new ATCommandException(response.Status);
		}