/// <summary>
        /// Reads one byte from the input stream.
        /// </summary>
        /// <remarks>This operation checks several things like the working mode in order to consider
        /// escaped bytes.</remarks>
        /// <param name="inputStream">The input stream to read bytes from.</param>
        /// <param name="mode">The XBee device working mode.</param>
        /// <returns>The read byte.</returns>
        /// <exception cref="InvalidPacketException">If there is not enough data in the stream
        /// or if there is an error verifying the checksum.</exception>
        /// <exception cref="ArgumentException">If input stream cannot be read.</exception>
        /// <exception cref="ArgumentNullException">If <paramref name="inputStream"/> is <c>null</c>.</exception>
        private int ReadByte(Stream inputStream, OperatingMode mode)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException("Input stream cannot be null.");
            }
            if (!inputStream.CanRead)
            {
                throw new ArgumentException("Could not read from the input stream.");
            }

            int timeout = 300;

            int b = ReadByteFrom(inputStream, timeout);

            if (b == -1)
            {
                throw new InvalidPacketException("Error parsing packet: Incomplete packet.");
            }

            /* Process the byte for API1. */

            if (mode == OperatingMode.API)
            {
                return(b);
            }

            /* Process the byte for API2. */

            // Check if the byte is special.
            if (!SpecialByte.ESCAPE_BYTE.IsSpecialByte((byte)b))
            {
                return(b);
            }

            // Check if the byte is ESCAPE.
            if (b == SpecialByte.ESCAPE_BYTE.GetValue())
            {
                // Read next byte and escape it.
                b = ReadByteFrom(inputStream, timeout);

                if (b == -1)
                {
                    throw new InvalidPacketException("Error parsing packet: Incomplete packet.");
                }

                b ^= 0x20;
            }
            else
            {
                // If the byte is not a escape there is a special byte not escaped.
                throw new InvalidPacketException("Special byte not escaped: 0x" + HexUtils.ByteToHexString((byte)(b & 0xFF)) + ".");
            }

            return(b);
        }
        private int ReadByte(SerialPort serialPort, OperatingMode mode)         /*throws InvalidPacketException, IOException*/
        {
            Contract.Requires <ArgumentNullException>(serialPort != null, "Input stream cannot be null.");
            Contract.Requires <ArgumentException>(serialPort.IsOpen);

            int timeout = 300;

            int b = ReadByteFrom(serialPort, timeout);

            if (b == -1)
            {
                throw new InvalidPacketException("Error parsing packet: Incomplete packet.");
            }

            /* Process the byte for API1. */

            if (mode == OperatingMode.API)
            {
                return(b);
            }

            /* Process the byte for API2. */

            // Check if the byte is special.
            if (!SpecialByte.ESCAPE_BYTE.IsSpecialByte((byte)b))
            {
                return(b);
            }

            // Check if the byte is ESCAPE.
            if (b == SpecialByte.ESCAPE_BYTE.GetValue())
            {
                // Read next byte and escape it.
                b = ReadByteFrom(serialPort, timeout);

                if (b == -1)
                {
                    throw new InvalidPacketException("Error parsing packet: Incomplete packet.");
                }

                b ^= 0x20;
            }
            else
            {
                // If the byte is not a escape there is a special byte not escaped.
                throw new InvalidPacketException("Special byte not escaped: 0x" + HexUtils.ByteToHexString((byte)(b & 0xFF)) + ".");
            }

            return(b);
        }
        /**
         * Parses the bytes from the given array depending on the provided operating
         * mode and returns the API packet.
         *
         * <p>The operating mode must be {@link OperatingMode#API} or
         * {@link OperatingMode#API_ESCAPE}.</p>
         *
         * @param packetByteArray Byte array with the complete frame, starting from
         *                        the header and ending in the checksum.
         * @param mode XBee device operating mode.
         *
         * @return Parsed packet from the given byte array.
         *
         * @throws InvalidPacketException if there is not enough data in the array or
         *                                if there is an error verifying the checksum or
         *                                if the payload is invalid for the specified frame type.
         * @throws ArgumentException if {@code mode != OperatingMode.API } and
         *                              if {@code mode != OperatingMode.API_ESCAPE}.
         * @throws ArgumentNullException if {@code packetByteArray == null} or
         *                              if {@code mode == null}.
         *
         * @see XBeePacket
         * @see com.digi.xbee.api.models.OperatingMode#API
         * @see com.digi.xbee.api.models.OperatingMode#API_ESCAPE
         */
        public XBeePacket ParsePacket(byte[] packetByteArray, OperatingMode mode)
        {
            Contract.Requires <ArgumentNullException>(packetByteArray != null, "Packet byte array cannot be null.");
            Contract.Requires <ArgumentNullException>(mode != null, "Operating mode cannot be null.");
            Contract.Requires <ArgumentException>(mode == OperatingMode.API || mode == OperatingMode.API_ESCAPE, "Operating mode must be API or API Escaped.");
            Contract.Requires <InvalidOperationException>(packetByteArray.Length >= 4, "Error parsing packet: Incomplete packet.");

            // Check the header of the frame.
            if ((packetByteArray[0] & 0xFF) != SpecialByte.HEADER_BYTE.GetValue())
            {
                throw new InvalidPacketException("Invalid start delimiter (expected 0x"
                                                 + HexUtils.ByteToHexString((byte)SpecialByte.HEADER_BYTE.GetValue()) + ").");
            }

            return(ParsePacket(new MemoryStream(packetByteArray, 1, packetByteArray.Length - 1), mode));
        }
        /// <summary>
        /// Parses the bytes from the given <paramref name="inputStream"/> depending on the provided
        /// <paramref name="mode"/> and returns the API packet.
        /// </summary>
        /// <remarks>The operating mode must be <see cref="OperatingMode.API"/> or
        /// <see cref="OperatingMode.API_ESCAPE"/>.</remarks>
        /// <param name="inputStream">Input stream to read bytes from.</param>
        /// <param name="mode">XBee device operating mode.</param>
        /// <returns>Parsed packet from the input stream.</returns>
        /// <exception cref="ArgumentException">If <paramref name="mode"/> is invalid
        /// or if the <paramref name="inputStream"/> cannot be read.</exception>
        /// <exception cref="ArgumentNullException">If <paramref name="inputStream"/> is <c>null</c>.</exception>
        /// <exception cref="InvalidPacketException">If there is not enough data in the stream or if there
        /// is an error verifying the checksum or if the payload is invalid for the specified frame type.</exception>
        public XBeePacket ParsePacket(Stream inputStream, OperatingMode mode)
        {
            if (inputStream == null)
            {
                throw new ArgumentNullException("Input stream cannot be null.");
            }
            if (!inputStream.CanRead)
            {
                throw new ArgumentException("Could not read from the input stream.");
            }
            if (mode != OperatingMode.API && mode != OperatingMode.API_ESCAPE)
            {
                throw new ArgumentException("Operating mode must be API or API Escaped.");
            }

            try
            {
                // Read packet size.
                int hSize  = ReadByte(inputStream, mode);
                int lSize  = ReadByte(inputStream, mode);
                int Length = hSize << 8 | lSize;

                // Read the payload.
                byte[] payload = ReadBytes(inputStream, mode, Length);

                // Calculate the expected checksum.
                XBeeChecksum checksum = new XBeeChecksum();
                checksum.Add(payload);
                byte expectedChecksum = (byte)(checksum.Generate() & 0xFF);

                // Read checksum from the input stream.
                byte readChecksum = (byte)(ReadByte(inputStream, mode) & 0xFF);

                // Verify the checksum of the read bytes.
                if (readChecksum != expectedChecksum)
                {
                    throw new InvalidPacketException("Invalid checksum (expected 0x"
                                                     + HexUtils.ByteToHexString(expectedChecksum) + ").");
                }

                return(ParsePayload(payload));
            }
            catch (IOException e)
            {
                throw new InvalidPacketException("Error parsing packet: " + e.Message, e);
            }
        }
        public XBeePacket ParsePacket(SerialPort serialPort, OperatingMode mode)
        {
            Contract.Requires <ArgumentNullException>(serialPort != null, "Input stream cannot be null.");
            Contract.Requires <ArgumentException>(serialPort.IsOpen);
            Contract.Requires <ArgumentException>(mode == OperatingMode.API || mode == OperatingMode.API_ESCAPE, "Operating mode must be API or API Escaped.");

            try
            {
                // Read packet size.
                int hSize  = ReadByte(serialPort, mode);
                int lSize  = ReadByte(serialPort, mode);
                int Length = hSize << 8 | lSize;

                // Read the payload.
                byte[] payload = ReadBytes(serialPort, mode, Length);

                // Calculate the expected checksum.
                XBeeChecksum checksum = new XBeeChecksum();
                checksum.Add(payload);
                byte expectedChecksum = (byte)(checksum.Generate() & 0xFF);

                // Read checksum from the input stream.
                byte readChecksum = (byte)(ReadByte(serialPort, mode) & 0xFF);

                // Verify the checksum of the read bytes.
                if (readChecksum != expectedChecksum)
                {
                    throw new InvalidPacketException("Invalid checksum (expected 0x"
                                                     + HexUtils.ByteToHexString(expectedChecksum) + ").");
                }

                return(ParsePayload(payload));
            }
            catch (IOException e)
            {
                throw new InvalidPacketException("Error parsing packet: " + e.Message, e);
            }
        }
        /// <summary>
        /// Parses the bytes from the given array depending on the provided operating mode and
        /// returns the API packet.
        /// </summary>
        /// <remarks>The operating mode must be <see cref="OperatingMode.API"/> or
        /// <see cref="OperatingMode.API_ESCAPE"/></remarks>
        /// <param name="packetByteArray">Byte array with the complete frame, starting from the
        /// header and ending in the checksum.</param>
        /// <param name="mode">XBee device operating mode.</param>
        /// <returns>Parsed packet from the given byte array.</returns>
        /// <exception cref="InvalidPacketException">If there is not enough data in the array
        /// or if there is an error verifying the checksum
        /// or if the payload is invalid for the specified frame type.</exception>
        /// <exception cref="ArgumentException">If <c><paramref name="mode"/> != <see cref="OperatingMode.API"/></c>
        /// and if <c><paramref name="mode"/> != <see cref="OperatingMode.API_ESCAPE"/></c></exception>
        /// <exception cref="ArgumentNullException">If <c><paramref name="packetByteArray"/> == null</c>.</exception>
        /// <seealso cref="XBeePacket"/>
        /// <seealso cref="OperatingMode.API"/>
        /// <seealso cref="OperatingMode.API_ESCAPE"/>
        public XBeePacket ParsePacket(byte[] packetByteArray, OperatingMode mode)
        {
            if (packetByteArray == null)
            {
                throw new ArgumentNullException("Packet byte array cannot be null.");
            }
            if (mode != OperatingMode.API && mode != OperatingMode.API_ESCAPE)
            {
                throw new ArgumentException("Operating mode must be API or API Escaped.");
            }
            if (packetByteArray.Length < 4)
            {
                throw new InvalidPacketException("Error parsing packet: Incomplete packet.");
            }

            // Check the header of the frame.
            if ((packetByteArray[0] & 0xFF) != SpecialByte.HEADER_BYTE.GetValue())
            {
                throw new InvalidPacketException("Invalid start delimiter (expected 0x"
                                                 + HexUtils.ByteToHexString(SpecialByte.HEADER_BYTE.GetValue()) + ").");
            }

            return(ParsePacket(new MemoryStream(packetByteArray, 1, packetByteArray.Length - 1), mode));
        }
Example #7
0
 /// <summary>
 /// Gets the string representation of the API output mode.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>String representation of the API output mode.</returns>
 public static string ToDisplayString(this APIOutputMode source)
 {
     return(HexUtils.ByteToHexString((byte)source) + ": " + lookupTable[source]);
 }
Example #8
0
 public static string ToDisplayString(this HardwareVersionEnum source)
 {
     return(string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source.GetValue()), source.GetDescription()));
 }
        public static string ToDisplayString(this AssociationIndicationStatus source)
        {
            var data = lookupTable[source];

            return(string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source), data));
        }
 public static string ToDisplayString(this PowerLevel source)
 {
     return(string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source), lookupTable[source]));
 }
 /// <summary>
 /// Returns the <see cref="ModemStatusEvent"/> in string format.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>The <see cref="ModemStatusEvent"/> in string format.</returns>
 public static string ToDisplayString(this ModemStatusEvent source)
 {
     return(string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)(int)source), source.GetDescription()));
 }
 /// <summary>
 /// Returns the <see cref="CellularAssociationIndicationStatus"/> in string format.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>The <see cref="CellularAssociationIndicationStatus"/> in string format.</returns>
 public static string ToDisplayString(this CellularAssociationIndicationStatus source)
 {
     return(string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)(int)source), source.GetDescription()));
 }
 /// <summary>
 /// Returns the <see cref="XBeeLocalInterface"/> in string format.
 /// </summary>
 /// <param name="source"></param>
 /// <returns>The <see cref="XBeeLocalInterface"/> in string format.</returns>
 public static string ToDisplayString(this XBeeLocalInterface source)
 {
     return(HexUtils.ByteToHexString((byte)source) + ": " + lookupTable[source]);
 }