diff --git a/.gitignore b/.gitignore
index dd9ba17..6fdb818 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@
**/bin
**/*.csproj.user
**/*.suo
+.vs/
+packages/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..a0f675c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,44 @@
+# How to Contribute
+
+## Getting help
+
+To ask questions about the XBee C# Library go to the
+[Digi Forum](http://www.digi.com/support/forum).
+
+
+## Reporting a bug
+
+The way to report bugs is to use the
+[GitHub issue tracker](http://github.com/digidotcom/xbee-csharp/issues).
+Before reporting a bug, please read the following points:
+
+1. Make sure that it is really a bug by checking the
+[documentation](https://www.digi.com/resources/documentation/digidocs/90002359/).
+2. If you still think you have found a bug, make sure someone has not already
+reported it. See the list of
+[known issues](http://github.com/digidotcom/xbee-csharp/issues).
+3. If it has not been reported yet, create a new issue. Make sure to add enough
+detail so that the bug can be reproduced.
+
+**Note**: The issue tracker is for bugs, not requests for help. Questions
+should be asked on the [Digi Forum](http://www.digi.com/support/forum) instead.
+
+
+## Suggesting a new feature
+
+1. Consult the [documentation](https://www.digi.com/resources/documentation/digidocs/90002359/)
+to ensure that the behavior you would like is not excluded.
+2. Make sure someone has not already requested it. See the list of
+[known issues](http://github.com/digidotcom/xbee-csharp/issues).
+3. Submit your request in the issue tracker.
+
+
+## Contributing code
+
+1. Fork the [XBee C# Library](http://github.com/digidotcom/xbee-csharp)
+repository ([how to fork a repo](https://help.github.com/articles/fork-a-repo/)).
+2. Create a branch for your contribution. Use a name that defines the purpose of the additions/modifications.
+3. Make your changes following the code style used in the library.
+4. Submit a pull request ([how to create a pull request](https://help.github.com/articles/fork-a-repo/#next-steps)).
+A project developer will review your work and then merge your request into the
+project, or come back to you with comments and/or questions.
diff --git a/README.md b/README.md
index becb1dc..bc96890 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,27 @@
-XBee C# Library
-=================
+# XBee C# Library [ ](https://www.nuget.org/packages/XBeeLibrary.Core/) [ ](https://www.nuget.org/packages/XBeeLibrary.Xamarin/)
This project contains the source code of the XBee C# Library, an easy-to-use
API developed in C# that allows you to interact with Digi International's
-[XBee](http://www.digi.com/xbee/) radio frequency (RF) modules.
+[XBee](http://www.digi.com/xbee/) radio frequency (RF) modules. This source has
+been contributed by [Digi International](http://www.digi.com) from the original
+work of Sébastien Rault.
-This source has been converted from the Java version provided by [Digi International](http://www.digi.com).
+The XBee C# library has two modules: **XBeeLibrary.Core**, which contains all
+the common code for any platform, and **XBeeLibrary.Xamarin**, which contains
+the necessary APIs to develop multi-platform mobile applications with Xamarin
+to communicate with XBee devices over Bluetooth Low Energy.
+
+The project includes the C# source code and multiple examples that show how to
+use the available APIs. The examples are also available in source code format.
The main features of the library include:
-* Support for ZigBee, 802.15.4, DigiMesh and Point-to-Multipoint XBee devices.
+* Support for ZigBee, 802.15.4, DigiMesh, Point-to-Multipoint and Cellular
+XBee devices.
* Support for API and API escaped operating modes.
-* Management of local (attached to the PC) and remote XBee device objects.
+* Support for communicating with XBee devices over Bluetooth Low Energy
+(XBeeLibrary.Xamarin).
+* Management of local (attached to the host) and remote XBee device objects.
* Discovery of remote XBee devices associated with the same network as the
local device.
* Configuration of local and remote XBee devices:
@@ -26,6 +36,7 @@ device.
* Reception of data from remote XBee devices:
* Data polling.
* Data reception callback.
+* Transmission and reception of IP and SMS messages.
* Reception of network status changes related to the local XBee device.
* IO lines management:
* Configure IO lines.
@@ -34,11 +45,36 @@ device.
* Receive IO data samples from any remote XBee device on the network.
* Support for explicit frames and application layer fields (Source endpoint,
Destination endpoint, Profile ID, and Cluster ID).
+* Support for User Data Relay frames, allowing the communication between
+different interfaces (Serial, Bluetooth Low Energy and MicroPython).
+
+
+## Start Here
+
+The best place to get started is the
+[XBee C# Library documentation](http://www.digi.com/resources/documentation/digidocs/90002359/).
+
-License
--------
-This software is open-source software. Copyright Sébastien RAULT, 2014-2015.
+## How to Contribute
+
+The contributing guidelines are in the
+[CONTRIBUTING.md](https://github.com/digidotcom/xbee-csharp/blob/master/CONTRIBUTING.md)
+document.
+
+
+## License
+
+Copyright 2019, Digi International Inc.
+Copyright 2014-2015, Sébastien RAULT.
This Source Code Form is subject to the terms of the Mozilla Public
-License, v. 2.0. If a copy of the MPL was not distributed with this file,
-you can obtain one at http://mozilla.org/MPL/2.0/.
+License, v. 2.0. If a copy of the MPL was not distributed with this
+file, you can obtain one at http://mozilla.org/MPL/2.0/.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/XBeeLibrary.Core/AbstractXBeeDevice.cs b/XBeeLibrary.Core/AbstractXBeeDevice.cs
new file mode 100644
index 0000000..f73457c
--- /dev/null
+++ b/XBeeLibrary.Core/AbstractXBeeDevice.cs
@@ -0,0 +1,3762 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using Common.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using XBeeLibrary.Core.Connection;
+using XBeeLibrary.Core.Events;
+using XBeeLibrary.Core.Events.Relay;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.IO;
+using XBeeLibrary.Core.Models;
+using XBeeLibrary.Core.Packet;
+using XBeeLibrary.Core.Packet.Common;
+using XBeeLibrary.Core.Packet.Raw;
+using XBeeLibrary.Core.Packet.Relay;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// This class provides common functionality for all XBee devices.
+ ///
+ ///
+ ///
+ public abstract class AbstractXBeeDevice
+ {
+ // Constants.
+ ///
+ /// Default receive timeout used to wait for a response in synchronous operations.
+ ///
+ ///
+ protected const int DEFAULT_RECEIVE_TIMETOUT = 2000; // 2.0 seconds of timeout to receive packet and command responses.
+
+ ///
+ /// Timeout to wait before entering in command mode.
+ ///
+ /// It is used to determine the operating mode of the module (this library only
+ /// supports API modes, not transparent mode).
+ ///
+ /// This value depends on the GT, AT and/or BT parameters.
+ ///
+ protected const int TIMEOUT_BEFORE_COMMAND_MODE = 1200;
+
+ ///
+ /// Timeout to wait after entering in command mode.
+ ///
+ /// It is used to determine the operating mode of the module (this library only supports
+ /// API modes, not transparent mode).
+ ///
+ /// This value depends on the GT, AT and/or BT parameters.
+ ///
+ protected const int TIMEOUT_ENTER_COMMAND_MODE = 1500;
+
+ protected const string PARAMETER_NODE_ID = "NI";
+
+ protected static int TIMEOUT_READ_PACKET = 3000;
+
+ private static int TIMEOUT_RESET = 5000;
+
+ private static string ERROR_OPENING_INTERFACE = "Error opening the connection interface > {0}";
+
+ private static string COMMAND_MODE_CHAR = "+";
+ private static string COMMAND_MODE_OK = "OK\r";
+
+ // Variables.
+ protected DataReader dataReader = null;
+
+ protected byte currentFrameID = 0xFF;
+ protected int receiveTimeout = DEFAULT_RECEIVE_TIMETOUT;
+
+ protected AbstractXBeeDevice localXBeeDevice;
+
+ protected ILog logger;
+
+ protected string bluetoothPassword;
+
+ protected XBeeNetwork network;
+
+ private OperatingMode operatingMode = OperatingMode.UNKNOWN;
+
+ private object ioLock = new object();
+ private object resetLock = new object();
+
+ private bool ioPacketReceived = false;
+ private bool modemStatusReceived = false;
+
+ private byte[] ioPacketPayload;
+
+ ///
+ /// Class constructor. Instantiates a new object with the given
+ /// connection interface.
+ ///
+ /// The connection interface with the physical XBee device.
+ /// If == null.
+ ///
+ ///
+ ///
+ public AbstractXBeeDevice(IConnectionInterface connectionInterface)
+ {
+ XBeeProtocol = XBeeProtocol.UNKNOWN;
+ ConnectionInterface = connectionInterface ?? throw new ArgumentNullException("ConnectionInterface cannot be null.");
+
+ // Obtain logger.
+ logger = LogManager.GetLogger(GetType());
+
+ logger.DebugFormat(ToString() + "Using the connection interface {0}.",
+ ConnectionInterface.GetType().Name);
+ }
+
+ ///
+ /// Class constructor. Instantiates a new object with the given
+ /// local XBee device which contains the connection interface to be used.
+ ///
+ /// The local XBee device that will behave as connection interface
+ /// to communicate with the remote XBee device.
+ /// The 64-bit address to identify this XBee device.
+ /// If localXBeeDevice.IsRemote == true.
+ /// If == null
+ /// or if == null.
+ ///
+ ///
+ ///
+ ///
+ public AbstractXBeeDevice(AbstractXBeeDevice localXBeeDevice, XBee64BitAddress addr64)
+ : this(localXBeeDevice, addr64, null, null) { }
+
+ ///
+ /// Class constructor. Instantiates a new object with the given
+ /// local XBee device which contains the connection interface to be used.
+ ///
+ /// The local XBee device that will behave as connection interface to
+ /// communicate with the remote XBee device.
+ /// The 64-bit address to identify this XBee device.
+ /// The 16-bit address to identify this XBee device. It might be null.
+ /// The node identifier of this XBee device. It might be null.
+ /// If is remote.
+ /// If == null
+ /// or if == null.
+ ///
+ ///
+ ///
+ ///
+ public AbstractXBeeDevice(AbstractXBeeDevice localXBeeDevice, XBee64BitAddress addr64,
+ XBee16BitAddress addr16, string id)
+ {
+ if (localXBeeDevice == null)
+ throw new ArgumentNullException("Local XBee device cannot be null.");
+ if (localXBeeDevice.IsRemote)
+ throw new ArgumentException("The given local XBee device is remote.");
+
+ XBeeProtocol = XBeeProtocol.UNKNOWN;
+ this.localXBeeDevice = localXBeeDevice;
+ ConnectionInterface = localXBeeDevice.ConnectionInterface;
+ XBee64BitAddr = addr64 ?? throw new ArgumentNullException("XBee 64-bit address of the device cannot be null.");
+ XBee16BitAddr = addr16;
+ if (addr16 == null)
+ XBee16BitAddr = XBee16BitAddress.UNKNOWN_ADDRESS;
+ NodeID = id;
+ logger = LogManager.GetLogger(GetType());
+ logger.DebugFormat(ToString() + "Using the connection interface {0}.",
+ ConnectionInterface.GetType().Name);
+ }
+
+ // Events.
+ ///
+ /// Represents the method that will handle the Packet received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected internal event EventHandler PacketReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.AddPacketReceivedHandler(value);
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.RemovePacketReceivedHandler(value);
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the Data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler DataReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.DataReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.DataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the IO Sample received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler IOSampleReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.IOSampleReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.IOSampleReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the Modem status received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler ModemStatusReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.ModemStatusReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.ModemStatusReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the explicit data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler ExplicitDataReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.ExplicitDataReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.ExplicitDataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the User Data Relay received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler UserDataRelayReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.UserDataRelayReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.UserDataRelayReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the Bluetooth data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler BluetoothDataReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.BluetoothDataReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.BluetoothDataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the MicroPython data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler MicroPythonDataReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.MicroPythonDataReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.MicroPythonDataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the serial data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler SerialDataReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.SerialDataReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.SerialDataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the SMS received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler SMSReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.SMSReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.SMSReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the IP data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ protected event EventHandler IPDataReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.IPDataReceived += value;
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.IPDataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the IO Packet received event.
+ ///
+ /// If the event handler is null.
+ ///
+ private event EventHandler IOPacketReceived
+ {
+ add
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.AddPacketReceivedHandler(value);
+ }
+ remove
+ {
+ if (value == null)
+ throw new ArgumentNullException("Event handler cannot be null.");
+ if (dataReader != null)
+ dataReader.RemovePacketReceivedHandler(value);
+ }
+ }
+
+ // Properties.
+ ///
+ /// The firmware version (hexadecimal string value) of this XBee device.
+ ///
+ /// To refresh this value use the method.
+ public string FirmwareVersion { get; private set; }
+
+ ///
+ /// The hardware version of this XBee device.
+ ///
+ /// If this value is null, use the method
+ /// to get its value.
+ ///
+ ///
+ public HardwareVersion HardwareVersion { get; private set; }
+
+ ///
+ /// The hardware version of this XBee device in string format (including the 0x prefix).
+ ///
+ /// If this value is empty, use the method
+ /// to get its value.
+ ///
+ public string HardwareVersionString
+ {
+ get
+ {
+ HardwareVersion hwVersion = HardwareVersion;
+ if (hwVersion == null)
+ return "";
+ string hexValue = HexUtils.IntegerToHexString(hwVersion.Value, 1);
+ int numZeros = 2 - hexValue.Length;
+ for (int i = 0; i < numZeros; i++)
+ hexValue = "0" + hexValue;
+ return "0x" + hexValue;
+ }
+ }
+
+ ///
+ /// The 16-bit address of this XBee device.
+ ///
+ /// To refresh this value, use the
+ /// method.
+ ///
+ public virtual XBee16BitAddress XBee16BitAddr { get; internal set; } = XBee16BitAddress.UNKNOWN_ADDRESS;
+
+ ///
+ /// The 64-bit address of this XBee device.
+ ///
+ /// If this value is null or
+ /// , use the
+ /// method to get its value.
+ ///
+ public virtual XBee64BitAddress XBee64BitAddr { get; internal set; } = XBee64BitAddress.UNKNOWN_ADDRESS;
+
+ ///
+ /// The XBee protocol of this XBee device.
+ ///
+ /// To refresh this value, use the method.
+ ///
+ public virtual XBeeProtocol XBeeProtocol { get; internal set; }
+
+ ///
+ /// The Signal strength of the device with the parent node. This value is cached at discovery
+ /// time and it is not read directly from the device.
+ ///
+ public int SignalStrength { get; set; }
+
+ ///
+ /// The Operating mode (AT, API or API escaped) of this XBee device for a local device,
+ /// and the operating mode of the local device used as communication interface for a remote device.
+ ///
+ ///
+ ///
+ protected OperatingMode OperatingMode
+ {
+ get
+ {
+ if (IsRemote)
+ return localXBeeDevice.OperatingMode;
+ return operatingMode;
+ }
+ set
+ {
+ operatingMode = value;
+ }
+ }
+
+ ///
+ /// The 'apply configuration changes' option for this device.
+ ///
+ /// Enabling this option means that when any parameter of this XBee device is set, it
+ /// will be also applied.
+ ///
+ /// If this option is disabled, the method must be used in order to
+ /// apply the changes in all the parameters that were previously set.
+ public bool ApplyConfigurationChangesEnabled { get; set; } = true;
+
+ ///
+ /// The node identifier of this XBee device.
+ ///
+ /// To refresh this value use the method.
+ public virtual string NodeID { get; internal set; }
+
+ ///
+ /// Indicates whether the XBee device is initialized (basic parameters have been read) or not.
+ ///
+ public bool IsInitialized { get; private set; } = false;
+
+ ///
+ /// Indicates whether this XBee device is a remote device.
+ ///
+ abstract public bool IsRemote { get; }
+
+ ///
+ /// The connection interface associated to this XBee device.
+ ///
+ ///
+ protected IConnectionInterface ConnectionInterface { get; private set; }
+
+ ///
+ /// The status of the connection interface associated to this device. It indicates if the connection
+ /// is open or not.
+ ///
+ ///
+ ///
+ protected internal bool IsOpen
+ {
+ get
+ {
+ if (ConnectionInterface != null)
+ return ConnectionInterface.IsOpen;
+ return false;
+ }
+ }
+
+ ///
+ /// The XBee device timeout in milliseconds for received packets in synchronous operations.
+ ///
+ /// If the value to be set is lesser than 0.
+ protected int ReceiveTimeout
+ {
+ get
+ {
+ return receiveTimeout;
+ }
+ set
+ {
+ if (value < 0)
+ throw new ArgumentException("Receive timeout cannot be less than 0.");
+
+ receiveTimeout = value;
+ }
+ }
+
+ ///
+ /// Indicates the API output mode of the XBee device.
+ ///
+ /// The API output mode determines the format that the received data is output through
+ /// the serial interface of the XBee device.
+ /// If the returned value of the API Output Mode command
+ /// is null or empty.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the given command.
+ /// If there is any other XBee related error.
+ ///
+ protected APIOutputMode APIOutputMode
+ {
+ get
+ {
+ var value = GetParameter("AO");
+ if (value == null || value.Length < 1)
+ throw new ATCommandEmptyException("AO");
+ return APIOutputMode.MODE_UNKNOWN.Get(value[0]);
+ }
+ set
+ {
+ if (value == APIOutputMode.MODE_UNKNOWN)
+ throw new ArgumentException("API output mode cannot be unknown.");
+ SetParameter("AO", new byte[] { value.GetValue() });
+ }
+ }
+
+ ///
+ /// Reads some parameters from this device and obtains its protocol.
+ ///
+ /// This method refresh the values of:
+ ///
+ /// - 64-bit address only if it is not initialized.
+ /// - Node Identifier.
+ /// - Hardware version if it is not initialized.
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - 16-bit address (not for DigiMesh modules).
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout reading the parameters.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ public virtual void ReadDeviceInfo()
+ {
+ byte[] response = null;
+ // Get the 64-bit address.
+ if (XBee64BitAddr == null || XBee64BitAddr.Equals(XBee64BitAddress.UNKNOWN_ADDRESS))
+ {
+ string addressHigh;
+ string addressLow;
+
+ response = GetParameter("SH");
+ if (response == null || response.Length < 1)
+ throw new ATCommandEmptyException("SH");
+ addressHigh = HexUtils.ByteArrayToHexString(response);
+
+ response = GetParameter("SL");
+ if (response == null || response.Length < 1)
+ throw new ATCommandEmptyException("SL");
+ addressLow = HexUtils.ByteArrayToHexString(response);
+
+ while (addressLow.Length < 8)
+ addressLow = "0" + addressLow;
+
+ XBee64BitAddr = new XBee64BitAddress(addressHigh + addressLow);
+ }
+ // Get the Node ID.
+ response = GetParameter("NI");
+ if (response == null || response.Length < 1)
+ throw new ATCommandEmptyException("NI");
+ NodeID = Encoding.UTF8.GetString(response, 0, response.Length);
+
+ // Get the hardware version.
+ if (HardwareVersion == null)
+ {
+ response = GetParameter("HV");
+ if (response == null || response.Length < 1)
+ throw new ATCommandEmptyException("HV");
+ HardwareVersion = HardwareVersion.Get(response[0]);
+ }
+
+ // Get the firmware version.
+ response = GetParameter("VR");
+ if (response == null || response.Length < 1)
+ throw new ATCommandEmptyException("VR");
+ FirmwareVersion = HexUtils.ByteArrayToHexString(response);
+ // Remove leading 0s.
+ if (FirmwareVersion.Length > 1)
+ FirmwareVersion = FirmwareVersion.TrimStart('0');
+
+ // Original value of the protocol.
+ XBeeProtocol origProtocol = XBeeProtocol;
+
+ // Obtain the device protocol.
+ XBeeProtocol currentProtocol = XBeeProtocol.UNKNOWN.DetermineProtocol(HardwareVersion, FirmwareVersion);
+
+ if (origProtocol != XBeeProtocol.UNKNOWN && origProtocol != currentProtocol)
+ {
+ throw new XBeeException("Error reading device information: Your module seems to be " + currentProtocol
+ + " and NOT " + origProtocol + ". Check if you are using the appropriate device class.");
+ }
+
+ XBeeProtocol = XBeeProtocol.UNKNOWN.DetermineProtocol(HardwareVersion, FirmwareVersion);
+
+ // Get the 16-bit address. This must be done after obtaining the protocol because
+ // DigiMesh and Point-to-Multipoint protocols don't have 16-bit addresses.
+ if (XBeeProtocol == XBeeProtocol.ZIGBEE
+ || XBeeProtocol == XBeeProtocol.RAW_802_15_4
+ || XBeeProtocol == XBeeProtocol.XTEND
+ || XBeeProtocol == XBeeProtocol.SMART_ENERGY
+ || XBeeProtocol == XBeeProtocol.ZNET)
+ {
+ response = GetParameter("MY");
+ if (response == null || response.Length < 1)
+ throw new ATCommandEmptyException("MY");
+ XBee16BitAddr = new XBee16BitAddress(response);
+ }
+
+ IsInitialized = true;
+ }
+
+ ///
+ /// Sets the configuration of the given IO line of this XBee device.
+ ///
+ /// The IO line to configure.
+ /// The IO mode to set to the IO line.
+ /// If is
+ /// or if is .
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set configuration command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ public virtual void SetIOConfiguration(IOLine ioLine, IOMode ioMode)
+ {
+ // Check IO line.
+ if (ioLine.Equals(IOLine.UNKNOWN))
+ throw new ArgumentException("IO line cannot be Unknown.");
+ if (ioMode.Equals(IOMode.UNKOWN))
+ throw new ArgumentException("IO mode cannot be Unknown.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ SetParameter(ioLine.GetConfigurationATCommand(), new byte[] { (byte)ioMode.GetId() });
+ }
+
+ ///
+ /// Returns the configuration mode of the provided IO line of this XBee device.
+ ///
+ /// The IO line to get its configuration.
+ /// The IO mode (configuration) of the provided IO line.
+ /// If is .
+ /// If the IO line AT command is empty.
+ /// If this device connection is not open.
+ /// If the received configuration mode is not valid.
+ /// If there is a timeout reading the IO command response.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ public virtual IOMode GetIOConfiguration(IOLine ioLine)
+ {
+ // Check IO line.
+ if (ioLine.Equals(IOLine.UNKNOWN))
+ throw new ArgumentException("DIO pin cannot be unknown.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ // Check if the received configuration mode is valid.
+ var ioModeAnswer = GetParameter(ioLine.GetConfigurationATCommand());
+ if (ioModeAnswer == null || ioModeAnswer.Length < 1)
+ throw new ATCommandEmptyException(ioLine.GetConfigurationATCommand());
+ int ioModeValue = ioModeAnswer[0];
+ IOMode dioMode = IOMode.UNKOWN.GetIOMode(ioModeValue, ioLine);
+ if (dioMode.Equals(IOMode.UNKOWN))
+ throw new OperationNotSupportedException("Received configuration mode '"
+ + HexUtils.IntegerToHexString(ioModeValue, 1) + "' is not valid.");
+
+ // Return the configuration mode.
+ return dioMode;
+ }
+
+ ///
+ /// Sets the digital value (high or low) to the provided IO line of this XBee device.
+ ///
+ /// The IO line to set its value.
+ /// The IOValue to set to the IO line or
+ /// .
+ /// If is
+ /// or if is .
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set configuration command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void SetDIOValue(IOLine ioLine, IOValue ioValue)
+ {
+ // Check IO line.
+ if (ioLine.Equals(IOLine.UNKNOWN))
+ throw new ArgumentException("IO line cannot be unknown.");
+ // Check IO value.
+ if (ioValue.Equals(IOValue.UNKNOWN))
+ throw new ArgumentException("IO value cannot be unknown.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ SetParameter(ioLine.GetConfigurationATCommand(), new byte[] { (byte)ioValue.GetID() });
+ }
+
+ ///
+ /// Returns the digital value of the provided IO line of this XBee device.
+ ///
+ /// The provided IO line must be previously configured as digital I/O. To do so, use
+ /// and the following :
+ ///
+ /// - to configure as digital input.
+ /// - to configure as digital output, high.
+ /// - to configure as digital output, low.
+ ///
+ /// The IO line to get its digital value.
+ /// If is .
+ /// If this device connection is not open.
+ /// If the sample does not contain the expected IO line and value.
+ /// If there is a timeout reading the command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual IOValue GetDIOValue(IOLine ioLine)
+ {
+ // Check IO line.
+ if (ioLine.Equals(IOLine.UNKNOWN))
+ throw new ArgumentException("IO line cannot be unknown.");
+
+ // Obtain an IO Sample from the XBee device.
+ IOSample ioSample = ReadIOSample();
+
+ // Check if the IO sample contains the expected IO line and value.
+ if (!ioSample.HasDigitalValues || !ioSample.DigitalValues.ContainsKey(ioLine))
+ throw new OperationNotSupportedException("Answer does not contain digital data for "
+ + ioLine.GetName() + ".");
+
+ // Return the digital value.
+ return ioSample.DigitalValues[ioLine];
+ }
+
+ ///
+ /// Sets the duty cycle (in %) of the provided IO line of this XBee device.
+ ///
+ /// The provided IO line must be:
+ ///
+ /// - PWM capable (IOLine.UNKNOWN.HasPWMCapability()).
+ /// - Previously configured as PWM Output (use
+ /// and ).
+ ///
+ /// The IO line to set its duty cycle value.
+ /// The duty cycle of the PWM.
+ /// If ioLine.HasPWMCapability() == false
+ /// or if value 0 or if value ]]> 100
+ /// or if is .
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set configuration command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual void SetPWMDutyCycle(IOLine ioLine, double dutyCycle)
+ {
+ // Check IO line.
+ if (ioLine.Equals(IOLine.UNKNOWN))
+ throw new ArgumentException("IO line cannot be unknown.");
+ // Check if the IO line has PWM capability.
+ if (!ioLine.HasPWMCapability())
+ throw new ArgumentException("Provided IO line does not have PWM capability.");
+ // Check duty cycle limits.
+ if (dutyCycle < 0 || dutyCycle > 100)
+ throw new ArgumentException("Duty Cycle must be between 0% and 100%.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ // Convert the value.
+ int finaldutyCycle = (int)(dutyCycle * 1023.0 / 100.0);
+
+ SetParameter(ioLine.GetPWMDutyCycleATCommand(), ByteUtils.IntToByteArray(finaldutyCycle));
+ }
+
+ ///
+ /// Gets the duty cycle (in %) corresponding to the provided IO line of this XBee device.
+ ///
+ /// The provided IO line must be:
+ ///
+ /// - PWM capable (IOLine.UNKNOWN.HasPWMCapability()").
+ /// - Previously configured as PWM Output (use
+ /// and ).
+ ///
+ /// The IO line to get its PWM duty cycle.
+ /// The PWM duty cycle value corresponding to the provided IO line (0% - 100%).
+ /// If ioLine.HasPWMCapability() == false
+ /// or if is .
+ /// If the parameter of the IO line is empty.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the PWM command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual double GetPWMDutyCycle(IOLine ioLine)
+ {
+ // Check IO line.
+ if (ioLine.Equals(IOLine.UNKNOWN))
+ throw new ArgumentException("IO line cannot be unknown.");
+ // Check if the IO line has PWM capability.
+ if (!ioLine.HasPWMCapability())
+ throw new ArgumentException("Provided IO line does not have PWM capability.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ var value = GetParameter(ioLine.GetPWMDutyCycleATCommand());
+ if (value == null || value.Length < 1)
+ throw new ATCommandEmptyException(ioLine.GetPWMDutyCycleATCommand());
+
+ // Return the PWM duty cycle value.
+ int readValue = ByteUtils.ByteArrayToInt(value);
+ return Math.Round((readValue * 100.0 / 1023.0) * 100.0) / 100.0;
+ }
+
+ ///
+ /// Returns the analog value of the provided IO line of this XBee device.
+ ///
+ /// The provided IO line must be previously configured as ADC. To do so, use
+ /// and .
+ /// The IO line to get its analog value.
+ /// The analog value corresponding to the provided IO line.
+ /// If is
+ /// .
+ /// If this device connection is not open.
+ /// If the IO sample does not contain the
+ /// expeceted IO line and value.
+ /// If there is a timeout reading the IO sample data.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ public virtual int GetADCValue(IOLine ioLine)
+ {
+ // Check IO line.
+ if (ioLine.Equals(IOLine.UNKNOWN))
+ throw new ArgumentException("IO line cannot be null.");
+
+ // Obtain an IO Sample from the XBee device.
+ IOSample ioSample = ReadIOSample();
+
+ // Check if the IO sample contains the expected IO line and value.
+ if (!ioSample.HasAnalogValues || !ioSample.AnalogValues.ContainsKey(ioLine))
+ throw new OperationNotSupportedException("Answer does not contain analog data for "
+ + ioLine.GetName() + ".");
+
+ // Return the analog value.
+ return ioSample.AnalogValues[ioLine];
+ }
+
+ ///
+ /// Sets the 64-bit destination extended address of this XBee device.
+ ///
+ /// is the broadcast address for
+ /// the PAN. can be used to address the
+ /// Pan Coordinator.
+ /// 64-bit destination address to be configured.
+ /// If is null.
+ /// If this device connection is not open.
+ /// If there is a timeout setting the destination address.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected virtual void SetDestinationAddress(XBee64BitAddress xbee64BitAddress)
+ {
+ if (xbee64BitAddress == null)
+ throw new ArgumentNullException("Address cannot be null.");
+
+ // This method needs to apply changes after modifying the destination
+ // address, but only if the destination address could be set successfully.
+ bool applyChanges = ApplyConfigurationChangesEnabled;
+ if (applyChanges)
+ ApplyConfigurationChangesEnabled = false;
+
+ byte[] address = xbee64BitAddress.Value;
+ try
+ {
+ var dh = new byte[4];
+ var dl = new byte[4];
+ Array.Copy(address, 0, dh, 0, 4);
+ Array.Copy(address, 4, dl, 0, 4);
+ SetParameter("DH", dh);
+ SetParameter("DL", dl);
+ ApplyChanges();
+ }
+ finally
+ {
+ // Always restore the old value of the AC.
+ ApplyConfigurationChangesEnabled = applyChanges;
+ }
+ }
+
+ ///
+ /// Returns the 64-bit destination extended address of this XBee device.
+ ///
+ /// is the broadcast address for the
+ /// PAN. can be used to address the Pan
+ /// Coordinator.
+ /// 64-bit destination address.
+ /// If DH or DL values are empty.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the destination address.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected virtual XBee64BitAddress GetDestinationAddress()
+ {
+ var dh = GetParameter("DH");
+ if (dh == null || dh.Length < 1)
+ throw new ATCommandEmptyException("DH");
+ var dl = GetParameter("DL");
+ if (dl == null || dl.Length < 1)
+ throw new ATCommandEmptyException("DL");
+
+ byte[] address = new byte[dh.Length + dl.Length];
+
+ Array.Copy(dh, 0, address, 0, dh.Length);
+ Array.Copy(dl, 0, address, dh.Length, dl.Length);
+
+ return new XBee64BitAddress(address);
+ }
+
+ ///
+ /// Sets the IO sampling rate to enable periodic sampling in this XBee device.
+ ///
+ /// A sample rate of 0 ms. disables this feature.
+ ///
+ /// All enabled digital IO and analog inputs will be sampled and transmitted every
+ /// milliseconds to the configured destination address.
+ /// IO sampling rate in milliseconds.
+ /// If 0
+ /// or if ]]> 0xFFFF.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set IO sampling rate
+ /// command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ protected virtual void SetIOSamplingRate(int rate)
+ {
+ // Check range.
+ if (rate < 0 || rate > 0xFFFF)
+ throw new ArgumentException("Rate must be between 0 and 0xFFFF.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ SetParameter("IR", ByteUtils.IntToByteArray(rate));
+ }
+
+ ///
+ /// Returns the IO sampling rate of this XBee device.
+ ///
+ /// A sample rate of 0 ms. means the IO sampling feature is disabled.
+ ///
+ /// Periodic sampling allows this XBee module to take an IO sample and transmit it to a remote
+ /// device (configured in the destination address) at the configured periodic rate (ms).
+ /// IO sampling rate in milliseconds.
+ /// If IR value is empty.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the IO sampling rate command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ protected virtual int GetIOSamplingRate()
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ var rate = GetParameter("IR");
+ if (rate == null || rate.Length < 1)
+ throw new ATCommandEmptyException("IR");
+ return ByteUtils.ByteArrayToInt(rate);
+ }
+
+ ///
+ /// Sets the digital IO lines of this XBee device to be monitored and sampled whenever their status
+ /// changes.
+ ///
+ /// A null set of lines disables this feature.
+ ///
+ /// If a change is detected on an enabled digital IO pin, a digital IO sample is immediately
+ /// transmitted to the configured destination address.
+ ///
+ /// The destination address can be configured using the
+ /// method and retrieved by .
+ /// Set of IO lines to be monitored, null to disable this feature.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set IO change detect
+ /// command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ protected virtual void SetDIOChangeDetection(ISet lines)
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ byte[] bitfield = new byte[2];
+
+ if (lines != null)
+ {
+ foreach (IOLine line in lines)
+ {
+ int i = (byte)line;
+ if (i < 8)
+ bitfield[1] = (byte)(bitfield[1] | (1 << i));
+ else
+ bitfield[0] = (byte)(bitfield[0] | (1 << i - 8));
+ }
+ }
+
+ SetParameter("IC", bitfield);
+ }
+
+ ///
+ /// Returns the set of IO lines of this device that are monitored for change detection.
+ ///
+ /// A null set means the DIO change detection feature is disabled.
+ ///
+ /// Modules can be configured to transmit to the configured destination address a data sample
+ /// immediately whenever a monitored digital IO line changes state.
+ /// Set of digital IO lines that are monitored for change detection, null if
+ /// there are no monitored lines.
+ /// If IC value is empty.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the IO change detect command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ protected virtual ISet GetDIOChangeDetection()
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ var bitfield = GetParameter("IC");
+ if (bitfield == null || bitfield.Length < 1)
+ throw new ATCommandEmptyException("IC");
+ var lines = new HashSet();
+ int mask = (bitfield[0] << 8) + (bitfield[1] & 0xFF);
+
+ for (int i = 0; i < 16; i++)
+ {
+ if (ByteUtils.IsBitEnabled(mask, i))
+ lines.Add(IOLine.UNKNOWN.GetDIO(i));
+ }
+
+ if (lines.Count > 0)
+ return lines;
+ return null;
+ }
+
+ ///
+ /// Applies changes to all command registers causing queued command register values to be applied.
+ ///
+ /// This method must be invoked if the 'apply configuration changes' option is disabled
+ /// and the changes to this XBee device parameters must be applied.
+ ///
+ /// To know if the 'apply configuration changes' option is enabled, use the
+ /// property. Use it also to enable/disable this feature.
+ ///
+ /// Applying changes does not imply the modifications will persist through subsequent resets. To do
+ /// so, use the method.
+ /// If this device connection is not open.
+ /// If there is a timeout sending apply changes command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ public void ApplyChanges()
+ {
+ ExecuteParameter("AC");
+ }
+
+ ///
+ /// Returns an IO sample from this XBee device containing the value of all enabled digital IO and
+ /// analog input channels.
+ ///
+ /// An IO sample containing the value of all enabled digital IO and analog input channels.
+ /// If IS value is empty.
+ /// If this device connection is not open.
+ /// If there is a timeout getting the IO sample.
+ /// If there is any other XBee related error.
+ ///
+ public virtual IOSample ReadIOSample()
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ // Try to build an IO Sample from the sample payload.
+ byte[] samplePayload = null;
+ IOSample ioSample;
+
+ // The response to the IS command in local 802.15.4 devices is empty,
+ // so we have to create a packet listener to receive the IO sample.
+ if (!IsRemote && XBeeProtocol == XBeeProtocol.RAW_802_15_4)
+ {
+ ExecuteParameter("IS");
+ samplePayload = ReceiveRaw802IOPacket();
+ if (samplePayload == null)
+ throw new Exceptions.TimeoutException("Timeout waiting for the IO response packet.");
+ }
+ else
+ {
+ samplePayload = GetParameter("IS");
+ if (samplePayload == null || samplePayload.Length < 1)
+ throw new ATCommandEmptyException("IS");
+ }
+
+ try
+ {
+ ioSample = new IOSample(samplePayload);
+ }
+ catch (ArgumentException e)
+ {
+ throw new XBeeException("Couldn't create the IO sample.", e);
+ }
+ return ioSample;
+ }
+
+ ///
+ /// Sets the given parameter with the provided value in this XBee device.
+ ///
+ /// If the 'apply configuration changes' option is enabled in this device, the configured
+ /// value for the given parameter will be immediately applied, if not the method
+ /// must be invoked to apply it.
+ ///
+ /// Use to know if the 'apply configuration changes' option
+ /// is enabled, and also to enable/disable it.
+ ///
+ /// To make parameter modifications persist through subsequent resets use the
+ /// method.
+ /// The name of the parameter to be set.
+ /// The value of the parameter to set.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set configuration command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SetParameter(string parameter, byte[] parameterValue)
+ {
+ if (parameterValue == null)
+ throw new ArgumentNullException("Value of the parameter cannot be null.");
+
+ SendParameter(parameter, parameterValue);
+ }
+
+ ///
+ /// Gets the value of the given parameter from this XBee device.
+ ///
+ /// The name of the parameter to retrieve its value.
+ /// A byte array containing the value of the parameter.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the given command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public byte[] GetParameter(string parameter)
+ {
+ return SendParameter(parameter, null);
+ }
+
+ ///
+ /// Executes the given command in this XBee device.
+ ///
+ /// This method is intended to be used for those AT parameters that cannot be read
+ /// or written, they just execute some action in the XBee module.
+ /// The AT command to be executed.
+ /// If this device connection is not open.
+ /// If there is a timeout executing the given command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public void ExecuteParameter(string parameter)
+ {
+ SendParameter(parameter, null);
+ }
+
+ ///
+ /// Performs a software reset on this XBee device and blocks until the process is
+ /// completed.
+ ///
+ abstract public void Reset();
+
+ ///
+ /// Performs a software reset on this XBee device and blocks until the process is
+ /// completed.
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout resetting the device.
+ /// If there is any other XBee related error.
+ protected void SoftwareReset()
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ logger.Info(ToString() + "Resetting the local module...");
+
+ ATCommandResponse response = null;
+ try
+ {
+ response = SendATCommand(new ATCommand("FR"));
+ }
+ catch (IOException e)
+ {
+ throw new XBeeException("Error writing in the communication interface.", e);
+ }
+
+ // Check if AT Command response is valid.
+ CheckATCommandResponseIsValid(response);
+
+ // Wait for a Modem Status packet.
+ if (!WaitForModemResetStatusPacket())
+ throw new Exceptions.TimeoutException("Timeout waiting for the Modem Status packet.");
+
+ logger.Info(ToString() + "Module reset successfully.");
+ }
+
+ ///
+ /// Returns the string representation of this device.
+ ///
+ /// The string representation of this device.
+ public override string ToString()
+ {
+ string id = NodeID ?? "";
+ string addr64 = XBee64BitAddr == null || XBee64BitAddr.Equals(XBee64BitAddress.UNKNOWN_ADDRESS) ?
+ "" : XBee64BitAddr.ToString();
+
+ if (id.Length == 0 && addr64.Length == 0)
+ return ConnectionInterface.ToString();
+
+ StringBuilder message = new StringBuilder(ConnectionInterface.ToString());
+ message.Append(addr64);
+ if (id.Length > 0)
+ {
+ message.Append(" (");
+ message.Append(id);
+ message.Append(")");
+ }
+ message.Append(" - ");
+
+ return message.ToString();
+ }
+
+ ///
+ /// Sets the Node Identifier on the device.
+ ///
+ /// The new Node ID.
+ /// If the length of the value to be set is greater than
+ /// 20 characters.
+ /// If the value to set is null.
+ /// If this device connection is not open.
+ /// If there is a timeout setting the node identifier command.
+ /// If there is any other XBee related error.
+ public virtual void SetNodeID(string nodeId)
+ {
+ if (nodeId == null)
+ throw new ArgumentNullException("Node ID cannot be null.");
+ if (nodeId.Length > 20)
+ throw new ArgumentException("Node ID length must be less than 21.");
+
+ SetParameter("NI", Encoding.UTF8.GetBytes(nodeId));
+ NodeID = nodeId;
+ }
+
+ ///
+ /// Returns the operating PAN ID (Personal Area Network Identifier) of this XBee device.
+ ///
+ /// For modules to communicate they must be configured with the same identifier. Only modules
+ /// with matching IDs can communicate with each other. This parameter allows multiple networks to
+ /// co-exist on the same physical channel.
+ /// The operating PAN ID of this XBee device.
+ /// If the ID command returns a null or an
+ /// empty value.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the operating PAN ID.
+ /// If there is any other XBee related error.
+ ///
+ protected byte[] GetPANID()
+ {
+ string parameter;
+ switch (XBeeProtocol)
+ {
+ case XBeeProtocol.ZIGBEE:
+ parameter = "OP";
+ break;
+ default:
+ parameter = "ID";
+ break;
+ }
+ var panIDAnswer = GetParameter(parameter);
+ if (panIDAnswer == null || panIDAnswer.Length < 1)
+ throw new ATCommandEmptyException(parameter);
+ return panIDAnswer;
+ }
+
+ ///
+ /// Sets the PAN ID (Personal Area Network Identifier) of this XBee device.
+ ///
+ /// For modules to communicate they must be configured with the same identifier. Only
+ /// modules with matching IDs can communicate with each other. This parameter allows multiple
+ /// networks to co-exist on the same physical channel.
+ /// The new PAN ID of this XBee device.
+ /// If the length of is 0
+ /// or if ]]> 8.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If there is a timeout setting the operating PAN ID.
+ /// If there is any other XBee related error.
+ ///
+ protected virtual void SetPANID(byte[] panID)
+ {
+ if (panID == null)
+ throw new ArgumentNullException("PAN ID cannot be null.");
+ if (panID.Length == 0)
+ throw new ArgumentException("Length of the PAN ID cannot be 0.");
+ if (panID.Length > 8)
+ throw new ArgumentException("Length of the PAN ID cannot be longer than 8 bytes.");
+
+ SetParameter("ID", panID);
+ }
+
+ ///
+ /// Returns the output power level at which this XBee device transmits conducted power.
+ ///
+ /// The output power level of this XBee device.
+ /// If the PL command returns a null or an
+ /// empty value.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the power level command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected virtual PowerLevel GetPowerLevel()
+ {
+ var powerLevelValue = GetParameter("PL");
+ if (powerLevelValue == null || powerLevelValue.Length < 1)
+ throw new ATCommandEmptyException("PL");
+ return PowerLevel.LEVEL_UNKNOWN.Get((byte)ByteUtils.ByteArrayToInt(powerLevelValue));
+ }
+
+ ///
+ /// Sets the output power level at which this XBee device transmits conducted power.
+ ///
+ /// The new output power level to be set in this XBee device.
+ /// If
+ /// is .
+ /// If this device connection is not open.
+ /// If there is a timeout setting the power level command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected virtual void SetPowerLevel(PowerLevel powerLevel)
+ {
+ if (powerLevel.Equals(PowerLevel.LEVEL_UNKNOWN))
+ throw new ArgumentException("Power level cannot be unknown.");
+
+ SetParameter("PL", ByteUtils.IntToByteArray(powerLevel.GetValue()));
+ }
+
+ ///
+ /// Writes configurable parameter values to the non-volatile memory of this XBee device so that parameter
+ /// modifications persist through subsequent resets.
+ ///
+ /// Parameters values remain in this device's memory until overwritten by subsequent use of this
+ /// method.
+ ///
+ /// If changes are made without writing them to non-volatile memory, the module reverts back to previously
+ /// saved parameters the next time the module is powered-on.
+ ///
+ /// Writing the parameter modifications does not mean those values are immediately applied, this depends
+ /// on the status of the 'apply configuration changes' option. Use
+ /// to get its status and to enable/disable the option. If it is disabled, method
+ /// can be used in order to manually apply the changes.
+ /// If this device connection is not open.
+ /// If there is a timeout executing the write settings command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ public void WriteChanges()
+ {
+ ExecuteParameter("WR");
+ }
+
+ ///
+ /// Enables the Bluetooth interface of this XBee device.
+ ///
+ ///
+ /// To work with this interface, you must also configure the Bluetooth password if not done
+ /// previously. You can use the method for
+ /// that purpose.
+ /// Note that your device must have Bluetooth Low Energy support to use this method.
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout enabling the interface.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public void EnableBluetooth()
+ {
+ EnableBluetooth(true);
+ }
+
+ ///
+ /// Disables the Bluetooth interface of this XBee device.
+ ///
+ ///
+ /// Note that your device must have Bluetooth Low Energy support to use this method.
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout disabling the interface.
+ /// If there is any other XBee related error.
+ ///
+ public void DisableBluetooth()
+ {
+ EnableBluetooth(false);
+ }
+
+ ///
+ /// Enables or disables the Bluetooth interface of this XBee device.
+ ///
+ /// true to enable the Bluetooth interface, false to
+ /// disable it.
+ /// If this device connection is not open.
+ /// If there is a timeout enabling or disabling the interface.
+ /// If there is any other XBee related error.
+ private void EnableBluetooth(bool enable)
+ {
+ SetParameter("BT", new byte[] { (byte)(enable ? 0x01 : 0x00) });
+ WriteChanges();
+ }
+
+ ///
+ /// Reads and returns the EUI-48 Bluetooth MAC address of this XBee device in a format such
+ /// as 00112233AABB.
+ ///
+ ///
+ /// Note that your device must have Bluetooth Low Energy support to use this method.
+ ///
+ /// The Bluetooth MAC address.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the MAC address.
+ /// If there is any other XBee related error.
+ public string GetBluetoothMacAddress()
+ {
+ return HexUtils.ByteArrayToHexString(GetParameter("BL"));
+ }
+
+ ///
+ /// Changes the password of this Bluetooth device with the new one provided.
+ ///
+ ///
+ /// Note that your device must have Bluetooth Low Energy support to use this method.
+ ///
+ /// New Bluetooth password.
+ /// If this device connection is not open.
+ /// If there is a timeout changing the Bluetooth password.
+ /// If there is any other XBee related error.
+ public void UpdateBluetoothPassword(string newPassword)
+ {
+ // Generate a new salt and verifier.
+ byte[] salt = SRP.Utils.GenerateSalt();
+ byte[] verifier = SRP.Utils.GenerateVerifier(salt, newPassword);
+
+ // Set the salt.
+ SetParameter("$S", salt);
+
+ // Set the verifier (split in 4 settings).
+ int index = 0;
+ int atLength = verifier.Length / 4;
+ byte[] part = new byte[atLength];
+
+ Array.Copy(verifier, index, part, 0, atLength);
+ SetParameter("$V", part);
+ index += atLength;
+ Array.Copy(verifier, index, part, 0, atLength);
+ SetParameter("$W", part);
+ index += atLength;
+ Array.Copy(verifier, index, part, 0, atLength);
+ SetParameter("$X", part);
+ index += atLength;
+ Array.Copy(verifier, index, part, 0, atLength);
+ SetParameter("$Y", part);
+
+ // Write changes.
+ WriteChanges();
+ }
+
+ ///
+ /// Returns the address of the device in string format.
+ ///
+ /// The address of the device in string format.
+ public string GetAddressString()
+ {
+ if (XBee64BitAddr != null)
+ return XBee64BitAddr.ToString();
+ else if (XBee16BitAddr != null)
+ return XBee16BitAddr.ToString();
+ else
+ return "";
+ }
+
+ ///
+ /// Configures the 16-bit address (network address) of this XBee device with the provided one.
+ ///
+ /// The new 16-bit address.
+ /// If == null.
+ /// If this device connection is not open.
+ ///
+ ///
+ internal void Set16BitAddress(XBee16BitAddress xbee16BitAddress)
+ {
+ if (xbee16BitAddress == null)
+ throw new ArgumentNullException("16-bit address canot be null.");
+
+ SetParameter("MY", xbee16BitAddress.Value);
+ XBee16BitAddr = xbee16BitAddress;
+ }
+
+ ///
+ /// Updates the current device reference with the data provided for the given device.
+ ///
+ /// This is only for internal use.
+ /// The XBee Device to get the data from.
+ internal void UpdateDeviceDataFrom(AbstractXBeeDevice device)
+ {
+ // Only update the Node Identifier if the provided is not null.
+ if (device.NodeID != null)
+ NodeID = device.NodeID;
+
+ // Only update the 64-bit address if the original is null or unknown.
+ XBee64BitAddress addr64 = device.XBee64BitAddr;
+ if (addr64 != null && !addr64.Equals(XBee64BitAddress.UNKNOWN_ADDRESS)
+ && !addr64.Equals(XBee64BitAddr)
+ && (XBee64BitAddr == null
+ || XBee64BitAddr.Equals(XBee64BitAddress.UNKNOWN_ADDRESS)))
+ {
+ XBee64BitAddr = addr64;
+ }
+
+ XBee16BitAddress addr16 = device.XBee16BitAddr;
+ if (addr16 != null && !addr16.Equals(XBee16BitAddr))
+ {
+ XBee16BitAddr = addr16;
+ }
+ }
+
+ ///
+ /// Sends the given AT command and waits for answer or until the configured receive timeout
+ /// expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ /// The AT command to be sent.
+ /// An object containing the response of the command or
+ /// null if there is no response.
+ /// If is null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If the received packet is invalid.
+ /// If there is a timeout sending the given AT command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ protected ATCommandResponse SendATCommand(ATCommand command)
+ {
+ // Check if command is null.
+ if (command == null)
+ throw new ArgumentNullException("AT command cannot be null.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ ATCommandResponse response = null;
+ OperatingMode operatingMode = OperatingMode;
+ 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 = XBee16BitAddr;
+ if (remote16BitAddress == null)
+ remote16BitAddress = XBee16BitAddress.UNKNOWN_ADDRESS;
+ RemoteATCommandOptions remoteATCommandOptions = RemoteATCommandOptions.OPTION_NONE;
+ if (ApplyConfigurationChangesEnabled)
+ remoteATCommandOptions |= RemoteATCommandOptions.OPTION_APPLY_CHANGES;
+ packet = new RemoteATCommandPacket(GetNextFrameID(), XBee64BitAddr, remote16BitAddress,
+ (byte)remoteATCommandOptions, command.Command, command.Parameter);
+ }
+ else
+ {
+ if (ApplyConfigurationChangesEnabled)
+ 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 c)
+ response = new ATCommandResponse(command, c.CommandValue, c.Status);
+ else if (answerPacket is RemoteATCommandResponsePacket r)
+ response = new ATCommandResponse(command, r.CommandValue, r.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;
+ }
+
+ ///
+ /// Sends the given XBee packet asynchronously.
+ ///
+ /// The method will not wait for an answer for the packet.
+ ///
+ /// To be notified when the answer is received, use
+ /// .
+ /// XBee packet to be sent.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void SendXBeePacketAsync(XBeePacket packet)
+ {
+ SendXBeePacket(packet, null);
+ }
+
+ ///
+ /// Sends the given XBee packet asynchronously and registers the given packet event handler (if
+ /// not null) to wait for an answer.
+ ///
+ /// XBee packet to be sent.
+ /// Event handler for the operation, null not to be notified when
+ /// the answer arrives.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ protected void SendXBeePacket(XBeePacket packet, EventHandler handler)
+ {
+ // Check if the packet to send is null.
+ if (packet == null)
+ throw new ArgumentNullException("XBee packet cannot be null.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ OperatingMode operatingMode = OperatingMode;
+ switch (operatingMode)
+ {
+ case OperatingMode.AT:
+ case OperatingMode.UNKNOWN:
+ default:
+ throw new InvalidOperatingModeException(operatingMode);
+ case OperatingMode.API:
+ case OperatingMode.API_ESCAPE:
+ // Add the required frame ID and event handler.
+ if (packet is XBeeAPIPacket)
+ {
+ XBeeAPIPacket apiPacket = (XBeeAPIPacket)packet;
+
+ if (handler != null && apiPacket.NeedsAPIFrameID)
+ dataReader.AddPacketReceivedHandler(handler, apiPacket.FrameID);
+ else if (handler != null)
+ dataReader.AddPacketReceivedHandler(handler);
+ }
+
+ // Write packet data.
+ WritePacket(packet);
+ break;
+ }
+ }
+
+ ///
+ /// Sends the given XBee packet synchronously and and blocks until response is received or receive
+ /// timeout is reached.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ ///
+ /// Use for non-blocking operations.
+ /// XBee packet to be sent.
+ /// An that contains the response of the sent packet or null
+ /// if there is no response.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If the configured time expires while waiting for the
+ /// packet reply.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ protected XBeePacket SendXBeePacket(XBeePacket packet)
+ {
+ // Check if the packet to send is null.
+ if (packet == null)
+ throw new ArgumentNullException("XBee packet cannot be null.");
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ OperatingMode operatingMode = OperatingMode;
+ switch (operatingMode)
+ {
+ case OperatingMode.AT:
+ case OperatingMode.UNKNOWN:
+ default:
+ throw new InvalidOperatingModeException(operatingMode);
+ case OperatingMode.API:
+ case OperatingMode.API_ESCAPE:
+ // Build response container.
+ var responseList = new List();
+
+ // If the packet does not need frame ID, send it async. and return null.
+ if (packet is XBeeAPIPacket)
+ {
+ if (!((XBeeAPIPacket)packet).NeedsAPIFrameID)
+ {
+ SendXBeePacketAsync(packet);
+ return null;
+ }
+ }
+ else
+ {
+ SendXBeePacketAsync(packet);
+ return null;
+ }
+
+ // Add the packet received event handler to the data reader.
+ EventHandler handler = (sender, e) => XBeePaketReceived(sender, e, packet, responseList);
+ dataReader.AddPacketReceivedHandler(handler);
+
+ // Write the packet data.
+ WritePacket(packet);
+ try
+ {
+ // Wait for response or timeout.
+ lock (responseList)
+ {
+ Monitor.Wait(responseList, receiveTimeout);
+ }
+ // After the wait check if we received any response, if not throw timeout exception.
+ if (responseList.Count < 1)
+ throw new Exceptions.TimeoutException();
+ // Return the received packet.
+ return responseList[0];
+ }
+ finally
+ {
+ // Always remove the packet received event handler from the list.
+ dataReader.RemovePacketReceivedHandler(handler);
+ }
+ }
+ }
+
+ ///
+ /// Gets the next Frame ID of this XBee device.
+ ///
+ /// The next Frame ID.
+ protected byte GetNextFrameID()
+ {
+ if (IsRemote)
+ return localXBeeDevice.GetNextFrameID();
+ if (currentFrameID == 0xff)
+ currentFrameID = 1; // Reset counter.
+ else
+ currentFrameID++;
+ return currentFrameID;
+ }
+
+ ///
+ /// Sends the provided and determines if the transmission
+ /// status is success for synchronous transmissions.
+ ///
+ /// If the status is not success, an is thrown.
+ /// The to be sent.
+ /// Determines whether the transmission must be asynchronous.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the received packet is not an instance of
+ /// or if is not an instance of
+ /// or if its transmit status is different from .
+ /// If there is any other XBee related error.
+ ///
+ protected void SendAndCheckXBeePacket(XBeePacket packet, bool asyncTransmission)
+ {
+ XBeePacket receivedPacket = null;
+
+ // Send the XBee packet.
+ try
+ {
+ if (asyncTransmission)
+ SendXBeePacketAsync(packet);
+ else
+ receivedPacket = SendXBeePacket(packet);
+ }
+ catch (IOException e)
+ {
+ throw new XBeeException("Error writing in the communication interface.", e);
+ }
+
+ // If the transmission is async. we are done.
+ if (asyncTransmission)
+ return;
+
+ // Check if the packet received is a valid transmit status packet.
+ if (receivedPacket == null)
+ throw new TransmitException(XBeeTransmitStatus.UNKNOWN);
+
+ XBeeTransmitStatus status = XBeeTransmitStatus.UNKNOWN;
+ if (receivedPacket is TransmitStatusPacket)
+ status = ((TransmitStatusPacket)receivedPacket).TransmitStatus;
+ else if (receivedPacket is TXStatusPacket)
+ status = ((TXStatusPacket)receivedPacket).TransmitStatus;
+
+ if (status != XBeeTransmitStatus.SUCCESS
+ && status != XBeeTransmitStatus.SELF_ADDRESSED)
+ throw new TransmitException(status);
+ }
+
+ ///
+ /// Checks if the provided is valid throwing an
+ /// in case it is not.
+ ///
+ /// The to check.
+ /// If == null
+ /// or if response.Status != .
+ ///
+ protected void CheckATCommandResponseIsValid(ATCommandResponse response)
+ {
+ if (response == null)
+ throw new ATCommandException(ATCommandStatus.UNKNOWN);
+ else if (response.Status != ATCommandStatus.OK)
+ throw new ATCommandException(response.Status);
+ }
+
+ ///
+ /// Returns the current association status of this XBee device.
+ ///
+ /// It indicates occurrences of errors during the last association request.
+ /// The association indication status of the XBee device.
+ /// If the AI command returns a null or an
+ /// empty value.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the association indication status.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected virtual AssociationIndicationStatus GetAssociationIndicationStatus()
+ {
+ var associationIndicationValue = GetParameter("AI");
+ if (associationIndicationValue == null || associationIndicationValue.Length < 1)
+ throw new ATCommandEmptyException("AI");
+ return AssociationIndicationStatus.NJ_EXPIRED.Get((byte)ByteUtils.ByteArrayToInt(associationIndicationValue));
+ }
+
+ ///
+ /// Forces this XBee device to immediately disassociate from the network and re-attempt to associate.
+ ///
+ /// Only valid for End Devices.
+ /// If this device connection is not open.
+ /// If there is a timeout executing the force disassociate command.
+ /// If there is any other XBee related error.
+ ///
+ protected void ForceDisassociate()
+ {
+ ExecuteParameter("DA");
+ }
+
+ ///
+ /// Sends the provided data to the given XBee local interface.
+ ///
+ /// Destination XBee local interface.
+ /// Data to send.
+ /// If the destination interface is unknown.
+ /// If there is any XBee related error sending the User
+ /// Data Relay.
+ ///
+ ///
+ ///
+ ///
+ protected void SendUserDataRelay(XBeeLocalInterface destinationInterface, byte[] data)
+ {
+ if (destinationInterface == XBeeLocalInterface.UNKNOWN)
+ throw new ArgumentException("Destination interface cannot be unknown.");
+
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send User Data Relay from a remote device.");
+
+ logger.DebugFormat(ToString() + "Sending User Data Relay to {0} >> {1}.",
+ destinationInterface.GetDescription(), HexUtils.PrettyHexString(data));
+
+ XBeePacket xbeePacket = new UserDataRelayPacket(GetNextFrameID(), destinationInterface, data);
+ // Send the packet asynchronously since User Data Relay frames do not receive any transmit status.
+ SendAndCheckXBeePacket(xbeePacket, true);
+ }
+
+ ///
+ /// Sends the given data to the XBee Bluetooth interface in a User Data Relay frame.
+ ///
+ /// Data to send.
+ /// If there is any XBee related error sending the Bluetooth
+ /// data.
+ ///
+ ///
+ ///
+ protected void SendBluetoothData(byte[] data)
+ {
+ SendUserDataRelay(XBeeLocalInterface.BLUETOOTH, data);
+ }
+
+ ///
+ /// Sends the given data to the XBee MicroPython interface in a User Data Relay frame.
+ ///
+ /// Data to send.
+ /// If there is any XBee related error sending the
+ /// MicroPython data.
+ ///
+ ///
+ ///
+ protected void SendMicroPythonData(byte[] data)
+ {
+ SendUserDataRelay(XBeeLocalInterface.MICROPYTHON, data);
+ }
+
+ ///
+ /// Sends the given data to the XBee serial interface in a User Data Relay frame.
+ ///
+ /// Data to send.
+ /// If there is any XBee related error sending the serial
+ /// data.
+ ///
+ ///
+ ///
+ protected void SendSerialData(byte[] data)
+ {
+ SendUserDataRelay(XBeeLocalInterface.SERIAL, data);
+ }
+
+ ///
+ /// Callback called after an XBee packet is received and the corresponding Packet Received event
+ /// has been fired.
+ ///
+ /// The object that sent the event.
+ /// The Packet Received event.
+ /// The sent packet to get its response.
+ /// The list to add the received response to.
+ ///
+ ///
+ private void XBeePaketReceived(object sender, PacketReceivedEventArgs e, XBeePacket sentPacket, IList responseList)
+ {
+ // Check if it is the packet we are waiting for.
+ if (((XBeeAPIPacket)e.ReceivedPacket).CheckFrameID((((XBeeAPIPacket)sentPacket).FrameID)))
+ {
+ // Security check to avoid class cast exceptions. It has been observed that parallel processes
+ // using the same connection but with different frame index may collide and cause this exception at some point.
+ if (sentPacket is XBeeAPIPacket && e.ReceivedPacket is XBeeAPIPacket)
+ {
+ XBeeAPIPacket sentAPIPacket = (XBeeAPIPacket)sentPacket;
+ XBeeAPIPacket receivedAPIPacket = (XBeeAPIPacket)e.ReceivedPacket;
+
+ // If the packet sent is an AT command, verify that the received one is an AT command response and
+ // the command matches in both packets.
+ if (sentAPIPacket.FrameType == APIFrameType.AT_COMMAND)
+ {
+ if (receivedAPIPacket.FrameType != APIFrameType.AT_COMMAND_RESPONSE)
+ return;
+ if (!((ATCommandPacket)sentAPIPacket).Command.Equals(((ATCommandResponsePacket)e.ReceivedPacket).Command, StringComparison.CurrentCultureIgnoreCase))
+ return;
+ }
+ // If the packet sent is a remote AT command, verify that the received one is a remote AT command response and
+ // the command matches in both packets.
+ if (sentAPIPacket.FrameType == APIFrameType.REMOTE_AT_COMMAND_REQUEST)
+ {
+ if (receivedAPIPacket.FrameType != APIFrameType.REMOTE_AT_COMMAND_RESPONSE)
+ return;
+ if (!((RemoteATCommandPacket)sentAPIPacket).Command.Equals(((RemoteATCommandResponsePacket)e.ReceivedPacket).Command, StringComparison.CurrentCultureIgnoreCase))
+ return;
+ }
+ }
+
+ // Verify that the sent packet is not the received one! This can happen when the echo mode is enabled in the
+ // serial port.
+ if (!IsSamePacket(sentPacket, e.ReceivedPacket))
+ {
+ responseList.Add(e.ReceivedPacket);
+ lock (responseList)
+ {
+ Monitor.Pulse(responseList);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Returns whether the sent packet is the same than the received one.
+ ///
+ /// The packet sent.
+ /// The packet received.
+ /// true if the sent packet is the same than the received one, false
+ /// otherwise.
+ ///
+ private bool IsSamePacket(XBeePacket sentPacket, XBeePacket receivedPacket)
+ {
+ // TODO Should not we implement the Equals method in the XBeePacket??
+ if (HexUtils.ByteArrayToHexString(sentPacket.GenerateByteArray()).Equals(HexUtils.ByteArrayToHexString(receivedPacket.GenerateByteArray())))
+ return true;
+ return false;
+ }
+
+ ///
+ /// Writes the given XBee packet in the connection interface of this device.
+ ///
+ /// The XBee packet to be written.
+ ///
+ private void WritePacket(XBeePacket packet)
+ {
+ logger.DebugFormat(ToString() + "Sending XBee packet: \n{0}", packet.ToPrettyString());
+ // Write bytes with the required escaping mode.
+ switch (operatingMode)
+ {
+ case OperatingMode.API:
+ default:
+ var buf = packet.GenerateByteArray();
+ ConnectionInterface.WriteData(buf, 0, buf.Length);
+ break;
+ case OperatingMode.API_ESCAPE:
+ var buf2 = packet.GenerateByteArrayEscaped();
+ ConnectionInterface.WriteData(buf2, 0, buf2.Length);
+ break;
+ }
+ }
+
+ ///
+ /// Returns the latest 802.15.4 IO packet and returns its value.
+ ///
+ /// The value of the latest received 802.15.4 IO packet.
+ private byte[] ReceiveRaw802IOPacket()
+ {
+ ioPacketReceived = false;
+ ioPacketPayload = null;
+ IOPacketReceived += ReceiveIOPacket;
+ lock (ioLock)
+ {
+ Monitor.Wait(ioLock, receiveTimeout);
+ }
+ IOPacketReceived -= ReceiveIOPacket;
+ if (ioPacketReceived)
+ return ioPacketPayload;
+ return null;
+ }
+
+ ///
+ /// Callback called after an IO sample packet is received and the corresponding Packet Received
+ /// event has been fired.
+ ///
+ /// The object that sent the event.
+ /// The Packet Received event.
+ ///
+ private void ReceiveIOPacket(object sender, PacketReceivedEventArgs e)
+ {
+ // Discard non API packets.
+ if (!(e.ReceivedPacket is XBeeAPIPacket))
+ return;
+ // If we already have received an IO packet, ignore this packet.
+ if (ioPacketReceived)
+ return;
+
+ // Save the packet value (IO sample payload)
+ switch (((XBeeAPIPacket)e.ReceivedPacket).FrameType)
+ {
+ case APIFrameType.IO_DATA_SAMPLE_RX_INDICATOR:
+ ioPacketPayload = ((IODataSampleRxIndicatorPacket)e.ReceivedPacket).RFData;
+ break;
+ case APIFrameType.RX_IO_16:
+ ioPacketPayload = ((RX16IOPacket)e.ReceivedPacket).RFData;
+ break;
+ case APIFrameType.RX_IO_64:
+ ioPacketPayload = ((RX64IOPacket)e.ReceivedPacket).RFData;
+ break;
+ default:
+ return;
+ }
+ // Set the IO packet received flag.
+ ioPacketReceived = true;
+
+ // Continue execution by notifying the lock object.
+ lock (ioLock)
+ {
+ Monitor.Pulse(ioLock);
+ }
+ }
+
+ ///
+ /// Sends the given AT parameter to this XBee device with an optional argument or value and
+ /// returns the response (likely the value) of that parameter in a byte array format.
+ ///
+ /// The name of the AT command to be executed.
+ /// The value of the parameter to set (if any).
+ /// A byte array containing the value of the parameter.
+ /// If is not 2 characters long.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the given AT command.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ private byte[] SendParameter(string parameter, byte[] parameterValue)
+ {
+ if (parameter == null)
+ throw new ArgumentNullException("Parameter cannot be null.");
+ if (parameter.Length != 2)
+ throw new ArgumentException("Parameter must contain exactly 2 characters.");
+
+ ATCommand atCommand = new ATCommand(parameter, parameterValue);
+
+ // Create and send the AT Command.
+ ATCommandResponse response = null;
+ try
+ {
+ response = SendATCommand(atCommand);
+ }
+ catch (IOException e)
+ {
+ throw new XBeeException("Error writing in the communication interface.", e);
+ }
+
+ // Check if AT Command response is valid.
+ CheckATCommandResponseIsValid(response);
+
+ // If the AT Command was written and corresponds to the Node Identifier,
+ // update it internally.
+ if (parameter.Equals(PARAMETER_NODE_ID)
+ && parameterValue != null
+ && parameterValue.Length > 0
+ && response.Status == ATCommandStatus.OK)
+ NodeID = Encoding.UTF8.GetString(parameterValue, 0, parameterValue.Length);
+
+ // Return the response value.
+ return response.Response;
+ }
+
+ ///
+ /// Opens the connection interface associated with this XBee device.
+ ///
+ /// When opening the device an information reading process is automatically performed.
+ /// This includes:
+ ///
+ /// - 64-bit address.
+ /// - Node Identifier.
+ /// - Hardware version
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - 16-bit address (not for DigiMesh modules).
+ ///
+ /// If this device connection is already open.
+ /// If the operating mode of the device is
+ /// or
+ /// If the BLE authentication process fails.
+ /// If the timeout to read settings when initializing the
+ /// device elapses without response.
+ /// If there is any problem opening this device connection.
+ ///
+ ///
+ protected virtual void Open()
+ {
+ logger.Info(ToString() + "Opening the connection interface...");
+
+ // First, verify that the connection is not already open.
+ if (ConnectionInterface.IsOpen)
+ throw new InterfaceAlreadyOpenException();
+
+ // Connect the interface.
+ try
+ {
+ ConnectionInterface.Open();
+ }
+ catch (Exception e)
+ {
+ throw new XBeeException(string.Format(ERROR_OPENING_INTERFACE, e.Message));
+ }
+
+ logger.Info(ToString() + "Connection interface open.");
+
+ // Initialize the data reader.
+ dataReader = new DataReader(ConnectionInterface, OperatingMode, this);
+ dataReader.Start();
+
+ // Wait 10 milliseconds until the dataReader thread is started.
+ // This is because when the connection is opened immediately after
+ // closing it, there is sometimes a concurrency problem and the
+ // dataReader thread never dies.
+ Task.Delay(10).Wait();
+
+ if (ConnectionInterface.GetConnectionType() == ConnectionType.BLUETOOTH)
+ {
+ // The communication in bluetooth is always done through API frames
+ // regardless of the AP setting.
+ OperatingMode = OperatingMode.API;
+ dataReader.SetXBeeReaderMode(OperatingMode);
+
+ // Perform the bluetooth authentication.
+ try
+ {
+ logger.Info(ToString() + "Starting bluetooth authentication...");
+ BluetoothAuthentication auth = new BluetoothAuthentication(this, bluetoothPassword);
+ auth.Authenticate();
+ ConnectionInterface.SetEncryptionKeys(auth.Key, auth.TxNonce, auth.RxNonce);
+ logger.Info(ToString() + "Authentication finished successfully.");
+ }
+ catch (Exception e)
+ {
+ Close();
+ throw e;
+ }
+ }
+ else
+ {
+ // Determine the operating mode of the XBee device if it is unknown.
+ if (OperatingMode == OperatingMode.UNKNOWN)
+ OperatingMode = DetermineOperatingMode();
+
+ // Check if the operating mode is a valid and supported one.
+ if (OperatingMode == OperatingMode.UNKNOWN)
+ {
+ Close();
+ throw new InvalidOperatingModeException("Could not determine operating mode.");
+ }
+ else if (OperatingMode == OperatingMode.AT)
+ {
+ Close();
+ throw new InvalidOperatingModeException(OperatingMode);
+ }
+ }
+
+ // Read the device info (obtain its parameters and protocol).
+ ReadDeviceInfo();
+ }
+
+ ///
+ /// Closes the connection interface associated with this XBee device.
+ ///
+ ///
+ ///
+ protected void Close()
+ {
+ // Stop XBee reader.
+ if (dataReader != null && dataReader.IsRunning)
+ dataReader.StopReader();
+ // Close interface.
+ ConnectionInterface.Close();
+ logger.Info(ToString() + "Connection interface closed.");
+ }
+
+ ///
+ /// Determines the operating mode of this XBee device.
+ ///
+ /// The operating mode of the XBee device.
+ /// If this device connection is not open.
+ /// If the packet is being sent from a remote
+ /// device.
+ /// If there is any other XBee related error.
+ ///
+ protected OperatingMode DetermineOperatingMode()
+ {
+ try
+ {
+ // Check if device is in API or API Escaped operating modes.
+ OperatingMode = OperatingMode.API;
+ dataReader.SetXBeeReaderMode(OperatingMode);
+
+ ATCommandResponse response = SendATCommand(new ATCommand("AP"));
+ if (response.Response != null && response.Response.Length > 0)
+ {
+ if (response.Response[0] != OperatingMode.API.GetID())
+ {
+ OperatingMode = OperatingMode.API_ESCAPE;
+ dataReader.SetXBeeReaderMode(OperatingMode);
+ }
+ logger.DebugFormat(ToString() + "Using {0}.", OperatingMode.GetName());
+ return OperatingMode;
+ }
+ }
+ catch (Exceptions.TimeoutException)
+ {
+ // Check if device is in AT operating mode.
+ OperatingMode = OperatingMode.AT;
+ dataReader.SetXBeeReaderMode(OperatingMode);
+
+ try
+ {
+ // It is necessary to wait at least 1 second to enter in
+ // command mode after sending any data to the device.
+ Task.Delay(TIMEOUT_BEFORE_COMMAND_MODE).Wait();
+ // Try to enter in AT command mode, if so the module is in AT mode.
+ bool success = EnterATCommandMode();
+ if (success)
+ return OperatingMode.AT;
+ }
+ catch (Exceptions.TimeoutException e1)
+ {
+ logger.Error(e1.Message, e1);
+ }
+ catch (System.TimeoutException e1)
+ {
+ logger.Error(e1.Message, e1);
+ }
+ catch (InvalidOperatingModeException e1)
+ {
+ logger.Error(e1.Message, e1);
+ }
+ }
+ catch (InvalidOperatingModeException e)
+ {
+ logger.Error("Invalid operating mode", e);
+ }
+ catch (IOException e)
+ {
+ logger.Error(e.Message, e);
+ }
+ return OperatingMode.UNKNOWN;
+ }
+
+ ///
+ /// Attempts to put this device in AT Command mode. Only valid if device is working in AT mode.
+ ///
+ /// true if the device entered in AT command mode, false otherwise.
+ /// If this device connection is not open.
+ /// If the operating mode cannot be determined
+ /// or is not supported.
+ /// If the configured time for this device expires.
+ private bool EnterATCommandMode()
+ {
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+ if (OperatingMode != OperatingMode.AT)
+ throw new InvalidOperatingModeException("Invalid mode. Command mode can be only accessed while in AT mode.");
+
+ // Enter in AT command mode (send '+++'). The process waits 1,5 seconds for the 'OK\n'.
+ byte[] readData = new byte[256];
+ try
+ {
+ // Send the command mode sequence.
+ var rawCmdModeChar = Encoding.UTF8.GetBytes(COMMAND_MODE_CHAR);
+ ConnectionInterface.WriteData(rawCmdModeChar, 0, rawCmdModeChar.Length);
+ ConnectionInterface.WriteData(rawCmdModeChar, 0, rawCmdModeChar.Length);
+ ConnectionInterface.WriteData(rawCmdModeChar, 0, rawCmdModeChar.Length);
+
+ // Wait some time to let the module generate a response.
+ Task.Delay(TIMEOUT_ENTER_COMMAND_MODE).Wait();
+
+ // Read data from the device (it should answer with 'OK\r').
+ int readBytes = ConnectionInterface.ReadData(readData, 0, readData.Length);
+ if (readBytes < COMMAND_MODE_OK.Length)
+ throw new Exceptions.TimeoutException();
+
+ // Check if the read data is 'OK\r'.
+ string readString = Encoding.UTF8.GetString(readData, 0, readBytes);
+ if (!readString.Contains(COMMAND_MODE_OK))
+ return false;
+
+ // Read data was 'OK\r'.
+ return true;
+ }
+ catch (IOException e)
+ {
+ logger.Error(e.Message, e);
+ }
+ return false;
+ }
+
+ ///
+ /// Returns the network associated with this XBee device.
+ ///
+ /// The XBee network of the device.
+ /// If this device connection is not open.
+ ///
+ protected internal virtual XBeeNetwork GetNetwork()
+ {
+ if (IsRemote)
+ throw new Exception("Remote devices do not have network.");
+
+ if (!IsOpen)
+ throw new InterfaceNotOpenException();
+
+ if (network == null)
+ network = new XBeeNetwork(this);
+ return network;
+ }
+
+ ///
+ /// Sends the given XBee packet and registers the given packet handler (if not null) to
+ /// manage what happens when the answer is received.
+ ///
+ /// This is a non-blocking operation. To wait for the answer use
+ /// .
+ /// XBee packet to be sent.
+ /// Event handler for the operation, null not to be notified when
+ /// the answer arrives.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ protected void SendPacket(XBeePacket packet, EventHandler handler)
+ {
+ try
+ {
+ SendXBeePacket(packet, handler);
+ }
+ catch (IOException e)
+ {
+ throw new XBeeException("Error writing in the communication interface.", e);
+ }
+ }
+
+ ///
+ /// Sends the given XBee packet asynchronously.
+ ///
+ /// To be notified when the answer is received, use the
+ /// event handler.
+ /// The XBee packet to be sent asynchronously.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ protected internal void SendPacketAsync(XBeePacket packet)
+ {
+ try
+ {
+ SendXBeePacket(packet, null);
+ }
+ catch (IOException e)
+ {
+ throw new XBeeException("Error writing in the communication interface.", e);
+ }
+ }
+
+ ///
+ /// Sends the given XBee packet synchronously and blocks until the response is received or
+ /// the configured receive timeout expires.
+ ///
+ /// The receive timeout is consulted/configured using the property.
+ ///
+ /// Use or
+ /// for non-blocking
+ /// operations.
+ /// The XBee packet to be sent.
+ /// An object containing the response of the sent packet or
+ /// null if there is no response.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If the configured time expires while waiting for the
+ /// packet reply.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ protected XBeePacket SendPacket(XBeePacket packet)
+ {
+ try
+ {
+ return SendXBeePacket(packet);
+ }
+ catch (IOException e)
+ {
+ throw new XBeeException("Error writing in the communication interface.", e);
+ }
+ }
+
+ ///
+ /// Sends the provided data to the provided XBee device asynchronously.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for
+ /// transmit status packet.
+ /// The XBee device of the network that will receive the data.
+ /// Byte array containing the data to be sent.
+ /// If this device connection is not open.
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the sender device is remote.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected virtual void SendDataAsync(RemoteXBeeDevice xbeeDevice, byte[] data)
+ {
+ if (xbeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null");
+ SendDataAsync(xbeeDevice.XBee64BitAddr, data);
+ }
+
+ ///
+ /// Sends the provided data to the given XBee device choosing the optimal send method depending
+ /// on the protocol of the local XBee device.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the property.
+ ///
+ /// For non-blocking operations use the method .
+ /// The XBee device of the network that will receive the data.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the data.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ protected virtual void SendData(RemoteXBeeDevice xbeeDevice, byte[] data)
+ {
+ if (xbeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null");
+
+ switch (XBeeProtocol)
+ {
+ case XBeeProtocol.ZIGBEE:
+ case XBeeProtocol.DIGI_POINT:
+ if (xbeeDevice.XBee64BitAddr != null && xbeeDevice.XBee16BitAddr != null)
+ SendData(xbeeDevice.XBee64BitAddr, xbeeDevice.XBee16BitAddr, data);
+ else
+ SendData(xbeeDevice.XBee64BitAddr, data);
+ break;
+ case XBeeProtocol.RAW_802_15_4:
+ if (this is Raw802Device)
+ {
+ if (xbeeDevice.XBee64BitAddr != null)
+ ((Raw802Device)this).SendData(xbeeDevice.XBee64BitAddr, data);
+ else
+ ((Raw802Device)this).SendData(xbeeDevice.XBee16BitAddr, data);
+ }
+ else
+ SendData(xbeeDevice.XBee64BitAddr, data);
+ break;
+ case XBeeProtocol.DIGI_MESH:
+ default:
+ SendData(xbeeDevice.XBee64BitAddr, data);
+ break;
+ }
+ }
+
+ ///
+ /// Sends the provided data to all the XBee nodes of the network (broadcast).
+ ///
+ /// This method blocks till a success or error transmit status arrives or the configured
+ /// receive timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the property.
+ ///
+ /// Byte array containing the data to be sent.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the data.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ protected virtual void SendBroadcastData(byte[] data)
+ {
+ SendData(XBee64BitAddress.BROADCAST_ADDRESS, data);
+ }
+
+ ///
+ /// Reads new data received by this XBee device during the configured receive timeout.
+ ///
+ /// This method blocks until new data is received or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ /// An object containing the data and the source address
+ /// of the remote node that sent the data. null if this did not receive new data during
+ /// the configured receive timeout.
+ /// If this device connection is not open.
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected virtual XBeeMessage ReadData()
+ {
+ return ReadDataPacket(null, TIMEOUT_READ_PACKET);
+ }
+
+ ///
+ /// Reads new data received by this XBee device during the provided timeout.
+ ///
+ /// This method blocks until new data is received or the provided timeout expires.
+ /// The time to wait for new data in milliseconds.
+ /// An object containing the data and the source address of
+ /// the remote node that sent the data. null if this did not receive new data during
+ /// milliseconds.
+ /// If 0.
+ /// If this device connection is not open.
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected virtual XBeeMessage ReadData(int timeout)
+ {
+ if (timeout < 0)
+ throw new ArgumentException("Read timeout must be 0 or greater.");
+
+ return ReadDataPacket(null, timeout);
+ }
+
+ ///
+ /// Reads new data received from the given remote XBee device during the configured received
+ /// timeout.
+ ///
+ /// This method blocks until new data is received or the provided timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ /// The remote device to read data from.
+ /// An object containing the data and the source address of
+ /// the remote node that sent the data. null if this did not receive new data during
+ /// the configured received timeout.
+ /// If is null.
+ /// If this device connection is not open.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected virtual XBeeMessage ReadDataFrom(RemoteXBeeDevice remoteXBeeDevice)
+ {
+ if (remoteXBeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null.");
+
+ return ReadDataPacket(remoteXBeeDevice, TIMEOUT_READ_PACKET);
+ }
+
+ ///
+ /// Reads new data received from the given remote XBee device during the provided timeout.
+ ///
+ /// This method blocks until new data from the provided remote XBee device is
+ /// received or the given timeout expires.
+ /// The remote device to read data from.
+ /// The time to wait for new data in milliseconds.
+ /// An object containing the data and the source address
+ /// of the remote node that sent the data. null if this did not receive new data during
+ /// milliseconds.
+ /// If 0.
+ /// If is null.
+ /// If this device connection is not open.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected virtual XBeeMessage ReadDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ if (remoteXBeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null.");
+ if (timeout < 0)
+ throw new ArgumentException("Read timeout must be 0 or greater.");
+
+ return ReadDataPacket(remoteXBeeDevice, timeout);
+ }
+
+ ///
+ /// Reads a new User Data Relay packet received by this XBee device during the configured receive
+ /// timeout.
+ ///
+ /// This method blocks until new User Data Relay is received or the configured receive
+ /// timeout expires.
+ /// A object containing the source interface and data.
+ /// null if this device did not receive new User Data Relay during the configured receive
+ /// timeout.
+ /// If the interface is not open.
+ ///
+ protected UserDataRelayMessage ReadUserDataRelay()
+ {
+ return ReadUserDataRelay(TIMEOUT_READ_PACKET);
+ }
+
+ ///
+ /// Reads a new User Data Relay packet received by this XBee device during the provided timeout.
+ ///
+ /// This method blocks until new User Data Relay is received or the given timeout
+ /// expires.
+ /// The time to wait for new User Data Relay in
+ /// milliseconds.
+ /// A object containing the source interface and data.
+ /// null if this device did not receive new User Data Relay during
+ /// milliseconds.
+ /// If the interface is not open.
+ ///
+ protected UserDataRelayMessage ReadUserDataRelay(int timeout)
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ XBeePacketsQueue xbeePacketsQueue = dataReader.XBeePacketsQueue;
+ XBeePacket xbeePacket = xbeePacketsQueue.GetFirstUserDataRelayPacket(timeout);
+
+ if (xbeePacket == null)
+ return null;
+
+ // Verify the packet is a User Data Relay packet.
+ APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).FrameType;
+ if (packetType != APIFrameType.USER_DATA_RELAY_OUTPUT)
+ return null;
+
+ // Obtain the necessary data from the packet.
+ UserDataRelayOutputPacket relayPacket = (UserDataRelayOutputPacket)xbeePacket;
+
+ // Create and return the User Data Relay message.
+ return new UserDataRelayMessage(relayPacket.SourceInterface, relayPacket.Data);
+ }
+
+ ///
+ /// Reads new explicit data received by this XBee device during the configured receive timeout.
+ ///
+ /// This method blocks until new explicit data is received or the configured receive
+ /// timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to
+ /// .
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this did not receive new explicit data during the configured receive timeout.
+ /// If the interface is not open.
+ ///
+ protected ExplicitXBeeMessage ReadExplicitData()
+ {
+ return ReadExplicitDataPacket(null, TIMEOUT_READ_PACKET);
+ }
+
+ ///
+ /// Reads new explicit data received by this XBee device during the configured receive timeout.
+ ///
+ /// This method blocks until new explicit data is received or the configured receive
+ /// timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to
+ /// .
+ /// The time to wait for new explicit data in milliseconds.
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this did not receive new explicit data during the configured receive timeout.
+ /// If 0.
+ /// If the interface is not open.
+ ///
+ protected ExplicitXBeeMessage ReadExplicitData(int timeout)
+ {
+ if (timeout < 0)
+ throw new ArgumentException("Read timeout must be 0 or greater.");
+
+ return ReadExplicitDataPacket(null, timeout);
+ }
+
+ ///
+ /// Reads new explicit data received from the given remote XBee device during the configured
+ /// receive timeout.
+ ///
+ /// This method blocks until new explicit data from the provided remote XBee device
+ /// is received or the configured receive timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to
+ /// .
+ /// The remote device to read explicit data from.
+ /// An object containing the explicit data, the
+ /// source address of the remote node that sent the data and other values related to the
+ /// transmission. null if this device did not receive new explicit data from the provided
+ /// remote XBee device during the configured receive timeout.
+ /// If == null.
+ /// If the interface is not open.
+ ///
+ ///
+ protected ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice)
+ {
+ if (remoteXBeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null.");
+
+ return ReadExplicitDataPacket(remoteXBeeDevice, TIMEOUT_READ_PACKET);
+ }
+
+ ///
+ /// Reads new explicit data received from the given remote XBee device during the provided
+ /// timeout.
+ ///
+ /// This method blocks until new explicit data from the provided remote XBee device is
+ /// received or the given timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to
+ /// .
+ /// The remote device to read explicit data from.
+ /// The time to wait for new explicit data in milliseconds.
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this device did not receive new data from the provided remote XBee device during
+ /// milliseconds.
+ /// If 0.
+ /// If == null.
+ /// If the interface is not open.
+ ///
+ ///
+ protected ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ if (remoteXBeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null.");
+ if (timeout < 0)
+ throw new ArgumentException("Read timeout must be 0 or greater.");
+
+ return ReadExplicitDataPacket(remoteXBeeDevice, timeout);
+ }
+
+ ///
+ /// Sends asynchronously the provided data in application layer mode to the XBee device of the
+ /// network corresponding to the given 64-bit address. Application layer mode means that you need
+ /// to specify the application layer fields to be sent with the data.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for
+ /// transmit status packet.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If == null
+ /// or if == null.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ /// If there is any other XBee related error.
+ ///
+ protected void SendExplicitDataAsync(XBee64BitAddress address, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ SendExplicitDataAsync(address, XBee16BitAddress.UNKNOWN_ADDRESS, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends asynchronously the provided data in application layer mode to the XBee device of the
+ /// network corresponding to the given 64-bit/16-bit address. Application layer mode means that
+ /// you need to specify the application layer fields to be sent with the data.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for
+ /// transmit status packet.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// The 16-bit address of the XBee that will receive the data.
+ /// If it is unknown the must be used.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If == null
+ /// or if == null
+ /// or if == null.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected void SendExplicitDataAsync(XBee64BitAddress address64Bits, XBee16BitAddress address16Bits,
+ byte sourceEndpoint, byte destEndpoint, byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ if (address64Bits == null)
+ throw new ArgumentNullException("64-bit address cannot be null.");
+ if (address16Bits == null)
+ throw new ArgumentNullException("16-bit address cannot be null.");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null.");
+ if (clusterID.Length != 2)
+ throw new ArgumentException("Cluster ID must be 2 bytes.");
+ if (profileID.Length != 2)
+ throw new ArgumentException("Profile ID must be 2 bytes.");
+
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send explicit data to a remote device from a remote device.");
+
+ logger.DebugFormat(ToString() + "Sending explicit data asynchronously to {0}[{1}] [{2} - {3} - {4} - {5}] >> {6}.",
+ address64Bits, address16Bits,
+ string.Format("%02X", sourceEndpoint), string.Format("%02X", destEndpoint),
+ string.Format("%04X", clusterID), string.Format("%04X", profileID),
+ HexUtils.PrettyHexString(data));
+
+ XBeePacket xbeePacket = new ExplicitAddressingPacket(GetNextFrameID(), address64Bits, address16Bits, sourceEndpoint,
+ destEndpoint, clusterID, profileID, 0, (byte)XBeeTransmitOptions.NONE, data);
+ SendAndCheckXBeePacket(xbeePacket, true);
+ }
+
+ ///
+ /// Sends asynchronously the provided data in application layer mode to the provided XBee device
+ /// choosing the optimal send method depending on the protocol of the local XBee device. Application
+ /// layer mode means that you need to specify the application layer fields to be sent with the data.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for transmit
+ /// status packet.
+ /// The XBee device of the network that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If == null
+ /// or if == null.
+ /// If the interface is not open.
+ /// If the sender device is remote or if the protocol
+ /// is .
+ /// If there is any other XBee related error.
+ ///
+ protected void SendExplicitDataAsync(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ if (remoteXBeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null.");
+
+ switch (remoteXBeeDevice.XBeeProtocol)
+ {
+ case XBeeProtocol.ZIGBEE:
+ case XBeeProtocol.DIGI_POINT:
+ if (remoteXBeeDevice.XBee64BitAddr != null && remoteXBeeDevice.XBee16BitAddr != null)
+ SendExplicitDataAsync(remoteXBeeDevice.XBee64BitAddr, remoteXBeeDevice.XBee16BitAddr, sourceEndpoint,
+ destEndpoint, clusterID, profileID, data);
+ else
+ SendExplicitDataAsync(remoteXBeeDevice.XBee64BitAddr, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ break;
+ case XBeeProtocol.RAW_802_15_4:
+ throw new OperationNotSupportedException("802.15.4. protocol does not support explicit data transmissions.");
+ case XBeeProtocol.DIGI_MESH:
+ default:
+ SendExplicitDataAsync(remoteXBeeDevice.XBee64BitAddr, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ break;
+ }
+ }
+
+ ///
+ /// Sends the provided data in application layer mode to the XBee device of the network corresponding
+ /// to the given 64-bit address. Application layer mode means that you need to specify the application
+ /// layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ protected void SendExplicitData(XBee64BitAddress address, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ SendExplicitData(address, XBee16BitAddress.UNKNOWN_ADDRESS, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data in application layer mode to the XBee device of the network corresponding
+ /// to the given 64-bit/16-bit address. Application layer mode means that you need to specify the
+ /// application layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ ///
+ /// The 64-bit address of the XBee that will receive the data.
+ /// The 16-bit address of the XBee that will receive the data.
+ /// If it is unknown the must be used.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ protected void SendExplicitData(XBee64BitAddress address64Bits, XBee16BitAddress address16Bits,
+ byte sourceEndpoint, byte destEndpoint, byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ if (address64Bits == null)
+ throw new ArgumentNullException("64-bit address cannot be null.");
+ if (address16Bits == null)
+ throw new ArgumentNullException("16-bit address cannot be null.");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null.");
+ if (clusterID.Length != 2)
+ throw new ArgumentException("Cluster ID must be 2 bytes.");
+ if (profileID.Length != 2)
+ throw new ArgumentException("Profile ID must be 2 bytes.");
+
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send explicit data to a remote device from a remote device.");
+
+ logger.DebugFormat(ToString() + "Sending explicit data to {0}[{1}] [{2} - {3} - {4} - {5}] >> {6}.",
+ address64Bits, address16Bits,
+ string.Format("%02X", sourceEndpoint), string.Format("%02X", destEndpoint),
+ string.Format("%04X", clusterID), string.Format("%04X", profileID),
+ HexUtils.PrettyHexString(data));
+
+ XBeePacket xbeePacket = new ExplicitAddressingPacket(GetNextFrameID(), address64Bits, address16Bits, sourceEndpoint,
+ destEndpoint, clusterID, profileID, 0, (byte)XBeeTransmitOptions.NONE, data);
+ SendAndCheckXBeePacket(xbeePacket, false);
+ }
+
+ ///
+ /// Sends the provided data in application layer mode to the provided XBee device choosing the
+ /// optimal send method depending on the protocol of the local XBee device. Application layer
+ /// mode means that you need to specify the application layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ /// The XBee device of the network that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the device protocol is
+ /// or if the sender device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ protected void SendExplicitData(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ if (remoteXBeeDevice == null)
+ throw new ArgumentNullException("Remote XBee device cannot be null.");
+
+ switch (remoteXBeeDevice.XBeeProtocol)
+ {
+ case XBeeProtocol.ZIGBEE:
+ case XBeeProtocol.DIGI_POINT:
+ if (remoteXBeeDevice.XBee64BitAddr != null && remoteXBeeDevice.XBee16BitAddr != null)
+ SendExplicitData(remoteXBeeDevice.XBee64BitAddr, remoteXBeeDevice.XBee16BitAddr, sourceEndpoint,
+ destEndpoint, clusterID, profileID, data);
+ else
+ SendExplicitData(remoteXBeeDevice.XBee64BitAddr, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ break;
+ case XBeeProtocol.RAW_802_15_4:
+ throw new OperationNotSupportedException("802.15.4. protocol does not support explicit data transmissions.");
+ case XBeeProtocol.DIGI_MESH:
+ default:
+ SendExplicitData(remoteXBeeDevice.XBee64BitAddr, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ break;
+ }
+ }
+
+ ///
+ /// Sends the provided data to all the XBee nodes of the network (broadcast) in application layer mode.
+ /// Application layer mode means that you need to specify the application layer fields to be sent with
+ /// the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the protocol of the device is
+ /// or if the sender device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ protected void SendBroadcastExplicitData(byte sourceEndpoint, byte destEndpoint, byte[] clusterID, byte[] profileID,
+ byte[] data)
+ {
+ if (XBeeProtocol == XBeeProtocol.RAW_802_15_4)
+ throw new OperationNotSupportedException("802.15.4. protocol does not support explicit data transmissions.");
+
+ SendExplicitData(XBee64BitAddress.UNKNOWN_ADDRESS, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data to the XBee device of the network corresponding to the given 64-bit
+ /// address.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout is consulted/configured using the property.
+ ///
+ /// For non-blocking operations use the method .
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the data.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void SendData(XBee64BitAddress address, byte[] data)
+ {
+ // Verify the parameters are not null, if they are null, throw an exception.
+ if (address == null)
+ throw new ArgumentNullException("Address cannot be null");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device.");
+
+ logger.DebugFormat(ToString() + "Sending data to {0} >> {1}.", address, HexUtils.PrettyHexString(data));
+
+ XBeePacket xbeePacket;
+ switch (XBeeProtocol)
+ {
+ case XBeeProtocol.RAW_802_15_4:
+ xbeePacket = new TX64Packet(GetNextFrameID(), address, (byte)XBeeTransmitOptions.NONE, data);
+ break;
+ default:
+ xbeePacket = new TransmitPacket(GetNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, 0, (byte)XBeeTransmitOptions.NONE, data);
+ break;
+ }
+ SendAndCheckXBeePacket(xbeePacket, false);
+ }
+
+ ///
+ /// Sends the provided data to the XBee device of the network corresponding to the given
+ /// 64-bit/16-bit address.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout is consulted/configured using the property.
+ ///
+ /// For non-blocking operations use the method
+ /// .
+ /// The 64-bit address of the XBee that will receive the data.
+ /// The 16-bit address of the XBee that will receive the data.If it is
+ /// unknown the must be used.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the data.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void SendData(XBee64BitAddress address64Bit, XBee16BitAddress address16bit, byte[] data)
+ {
+ // Verify the parameters are not null, if they are null, throw an exception.
+ if (address64Bit == null)
+ throw new ArgumentNullException("64-bit address cannot be null");
+ if (address16bit == null)
+ throw new ArgumentNullException("16-bit address cannot be null");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device.");
+
+ logger.DebugFormat(ToString() + "Sending data to {0}[{1}] >> {2}.",
+ address64Bit, address16bit, HexUtils.PrettyHexString(data));
+
+ XBeePacket xbeePacket = new TransmitPacket(GetNextFrameID(), address64Bit, address16bit, 0, (byte)XBeeTransmitOptions.NONE, data);
+ SendAndCheckXBeePacket(xbeePacket, false);
+ }
+
+ ///
+ /// Sends asynchronously the provided data to the XBee device of the network corresponding to the
+ /// given 64-bit address.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for
+ /// transmit status packet.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the sender device is remote.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void SendDataAsync(XBee64BitAddress address, byte[] data)
+ {
+ // Verify the parameters are not null, if they are null, throw an exception.
+ if (address == null)
+ throw new ArgumentNullException("Address cannot be null");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device.");
+
+ logger.DebugFormat(ToString() + "Sending data asynchronously to {0} >> {1}.", address, HexUtils.PrettyHexString(data));
+
+ XBeePacket xbeePacket;
+ switch (XBeeProtocol)
+ {
+ case XBeeProtocol.RAW_802_15_4:
+ xbeePacket = new TX64Packet(GetNextFrameID(), address, (byte)XBeeTransmitOptions.NONE, data);
+ break;
+ default:
+ xbeePacket = new TransmitPacket(GetNextFrameID(), address, XBee16BitAddress.UNKNOWN_ADDRESS, 0, (byte)XBeeTransmitOptions.NONE, data);
+ break;
+ }
+ SendAndCheckXBeePacket(xbeePacket, true);
+ }
+
+ ///
+ /// Sends asynchronously the provided data to the XBee device of the network corresponding to the
+ /// given 64-bit/16-bit address.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for
+ /// transmit status packet.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// The 16-bit address of the XBee that will receive the data.If it
+ /// is unknown the must be used.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the sender device is remote.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ protected void SendDataAsync(XBee64BitAddress address64Bit, XBee16BitAddress address16bit, byte[] data)
+ {
+ // Verify the parameters are not null, if they are null, throw an exception.
+ if (address64Bit == null)
+ throw new ArgumentNullException("64-bit address cannot be null");
+ if (address16bit == null)
+ throw new ArgumentNullException("16-bit address cannot be null");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device.");
+
+ logger.DebugFormat(ToString() + "Sending data asynchronously to {0}[{1}] >> {2}.",
+ address64Bit, address16bit, HexUtils.PrettyHexString(data));
+
+ XBeePacket xbeePacket = new TransmitPacket(GetNextFrameID(), address64Bit, address16bit, 0, (byte)XBeeTransmitOptions.NONE, data);
+ SendAndCheckXBeePacket(xbeePacket, true);
+ }
+
+ ///
+ /// Reads a new data packet received by this XBee device during the provided timeout.
+ ///
+ /// This method blocks until new data is received or the given timeout expires.
+ ///
+ /// If the provided remote XBee device is null the method returns the first data
+ /// packet read from any remote device.
+ ///
+ /// If the remote device is not null the method returns the first data package
+ /// read from the provided device.
+ /// The remote device to get a data packet from. null
+ /// to read a data packet sent by any remote XBee device.
+ /// The time to wait for a data packet in milliseconds.
+ /// An received by this device, containing the data and
+ /// the source address of the remote node that sent the data. null if this device
+ /// did not receive new data during milliseconds, or if any error occurs
+ /// while trying to get the source of the message.
+ /// If this device connection is not open.
+ ///
+ ///
+ private XBeeMessage ReadDataPacket(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ XBeePacketsQueue xbeePacketsQueue = dataReader.XBeePacketsQueue;
+ XBeePacket xbeePacket = null;
+
+ if (remoteXBeeDevice != null)
+ xbeePacket = xbeePacketsQueue.GetFirstDataPacketFrom(remoteXBeeDevice, timeout);
+ else
+ xbeePacket = xbeePacketsQueue.GetFirstDataPacket(timeout);
+
+ if (xbeePacket == null)
+ return null;
+
+ // Obtain the remote device from the packet.
+ RemoteXBeeDevice remoteDevice = null;
+ try
+ {
+ remoteDevice = dataReader.GetRemoteXBeeDeviceFromPacket((XBeeAPIPacket)xbeePacket);
+ // If the provided device is not null, add it to the network, so the
+ // device provided is the one that will remain in the network.
+ if (remoteXBeeDevice != null)
+ remoteDevice = GetNetwork().AddRemoteDevice(remoteXBeeDevice);
+
+ // The packet always contains information of the source so the
+ // remote device should never be null.
+ if (remoteDevice == null)
+ return null;
+
+ }
+ catch (XBeeException e)
+ {
+ logger.Error(e.Message, e);
+ return null;
+ }
+
+ // Obtain the data from the packet.
+ byte[] data = null;
+
+ switch (((XBeeAPIPacket)xbeePacket).FrameType)
+ {
+ case APIFrameType.RECEIVE_PACKET:
+ ReceivePacket receivePacket = (ReceivePacket)xbeePacket;
+ data = receivePacket.RFData;
+ break;
+ case APIFrameType.RX_16:
+ RX16Packet rx16Packet = (RX16Packet)xbeePacket;
+ data = rx16Packet.RFData;
+ break;
+ case APIFrameType.RX_64:
+ RX64Packet rx64Packet = (RX64Packet)xbeePacket;
+ data = rx64Packet.RFData;
+ break;
+ default:
+ return null;
+ }
+
+ // Create and return the XBee message.
+ return new XBeeMessage(remoteDevice, data, ((XBeeAPIPacket)xbeePacket).IsBroadcast);
+ }
+
+ ///
+ /// Reads a new explicit data packet received by this XBee device during the provided timeout.
+ ///
+ /// This method blocks until new explicit data is received or the given timeout
+ /// expires.
+ ///
+ /// If the provided remote XBee device is null the method returns the first explicit
+ /// data packet read from any remote device. If the remote device is not null the method
+ /// returns the first explicit data package read from the provided device.
+ /// The remote device to read explicit data from.
+ /// The time to wait for new explicit data in milliseconds.
+ /// An object containing the explicit data, the
+ /// source address of the remote node that sent the data and other values related to the
+ /// transmission. null if this device did not receive new data from the provided remote
+ /// XBee device during milliseconds.
+ /// If the interface is not open.
+ ///
+ ///
+ private ExplicitXBeeMessage ReadExplicitDataPacket(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ XBeePacketsQueue xbeePacketsQueue = dataReader.XBeePacketsQueue;
+ XBeePacket xbeePacket = null;
+
+ if (remoteXBeeDevice != null)
+ xbeePacket = xbeePacketsQueue.GetFirstExplicitDataPacketFrom(remoteXBeeDevice, timeout);
+ else
+ xbeePacket = xbeePacketsQueue.GetFirstExplicitDataPacket(timeout);
+
+ if (xbeePacket == null)
+ return null;
+
+ // Verify the packet is an explicit data packet.
+ APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).FrameType;
+ if (packetType != APIFrameType.EXPLICIT_RX_INDICATOR)
+ return null;
+
+ // Obtain the necessary data from the packet.
+ ExplicitRxIndicatorPacket explicitDataPacket = (ExplicitRxIndicatorPacket)xbeePacket;
+ RemoteXBeeDevice remoteDevice = GetNetwork().GetDevice(explicitDataPacket.SourceAddress64);
+ if (remoteDevice == null)
+ {
+ if (remoteXBeeDevice != null)
+ remoteDevice = remoteXBeeDevice;
+ else
+ remoteDevice = new RemoteXBeeDevice(this, explicitDataPacket.SourceAddress64);
+ GetNetwork().AddRemoteDevice(remoteDevice);
+ }
+ byte sourceEndpoint = explicitDataPacket.SourceEndpoint;
+ byte destEndpoint = explicitDataPacket.DestEndpoint;
+ byte[] clusterID = explicitDataPacket.ClusterID;
+ byte[] profileID = explicitDataPacket.ProfileID;
+ byte[] data = explicitDataPacket.RFData;
+
+ // Create and return the XBee message.
+ return new ExplicitXBeeMessage(remoteDevice, sourceEndpoint, destEndpoint, clusterID, profileID,
+ data, ((XBeeAPIPacket)xbeePacket).IsBroadcast);
+ }
+
+ ///
+ /// Waits until a Modem Status packet with a reset status,
+ /// (0x00), or a watchdog timer reset,
+ /// (0x01), is received or the
+ /// timeout expires.
+ ///
+ /// Reads modem status events from this XBee device during the configured
+ /// receive timeout.
+ /// true if the Modem Status packet is received, false otherwise.
+ ///
+ ///
+ private bool WaitForModemResetStatusPacket()
+ {
+ modemStatusReceived = false;
+
+ ModemStatusReceived += ResetModemStatusReceived;
+ lock (resetLock)
+ {
+ Monitor.Wait(resetLock, TIMEOUT_RESET);
+ }
+ ModemStatusReceived -= ResetModemStatusReceived;
+ return modemStatusReceived;
+ }
+
+ ///
+ /// Callback called after a Modem status packet is received and the corresponding
+ /// event has been fired.
+ ///
+ /// The object that sent the event.
+ /// The Packet Received event.
+ ///
+ private void ResetModemStatusReceived(object sender, ModemStatusReceivedEventArgs e)
+ {
+ if (e.ModemStatusEvent == ModemStatusEvent.STATUS_HARDWARE_RESET
+ || e.ModemStatusEvent == ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET)
+ {
+ modemStatusReceived = true;
+ // Continue execution by notifying the lock object.
+ lock (resetLock)
+ {
+ Monitor.Pulse(resetLock);
+ }
+ }
+ }
+
+ ///
+ /// Sets the password of this Bluetooth device in order to connect to it.
+ ///
+ ///
+ /// The Bluetooth password must be provided before calling the method.
+ ///
+ /// The password of this Bluetooth device.
+ protected void SetBluetoothPassword(string password)
+ {
+ bluetoothPassword = password;
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/BluetoothAuthentication.cs b/XBeeLibrary.Core/BluetoothAuthentication.cs
new file mode 100644
index 0000000..08c8493
--- /dev/null
+++ b/XBeeLibrary.Core/BluetoothAuthentication.cs
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using SRP;
+using System;
+using System.IO;
+using System.Threading;
+using XBeeLibrary.Core.Events;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.Models;
+using XBeeLibrary.Core.Packet;
+using XBeeLibrary.Core.Packet.Bluetooth;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// Helper class to perform the bluetooth authentication.
+ ///
+ class BluetoothAuthentication
+ {
+ // Constants.
+ private static readonly int TIMEOUT_AUTH = 20000;
+
+ private static readonly string API_USERNAME = "apiservice";
+
+ private static readonly string ERROR_AUTH = "Error performing authentication";
+ private static readonly string ERROR_AUTH_EXTENDED = ERROR_AUTH + " > {0}";
+ private static readonly string ERROR_RESPONSE_NOT_RECEIVED = "Server response not received.";
+ private static readonly string ERROR_WRITING = "Error writing in the communication interface.";
+ private static readonly string ERROR_BAD_PROOF = "Bad proof of key.";
+
+ private static readonly int LENGTH_SALT = 4;
+ private static readonly int LENGTH_EPHEMERAL = 128;
+ private static readonly int LENGTH_SESSION_PROOF = 32;
+ private static readonly int LENGTH_NONCE = 12;
+
+ // Variables.
+ private readonly AbstractXBeeDevice device;
+ private readonly string password;
+
+ private object unlockLock = new object();
+
+ private SrpPhase expectedPhase;
+
+ private BluetoothUnlockResponsePacket unlockResponse;
+
+ ///
+ /// Class constructor. Instantiates a new with the
+ /// given parameters.
+ ///
+ /// XBee device.
+ /// Bluetooth password.
+ ///
+ public BluetoothAuthentication(AbstractXBeeDevice device, string password)
+ {
+ this.device = device;
+ this.password = password;
+ }
+
+ // Properties.
+ ///
+ /// The session key.
+ ///
+ public byte[] Key { get; private set; }
+
+ ///
+ /// The TX nonce of the SRP authentication process.
+ ///
+ public byte[] TxNonce { get; private set; }
+
+ ///
+ /// The RX nonce of the SRP authentication process.
+ ///
+ public byte[] RxNonce { get; private set; }
+
+ ///
+ /// Starts the bluetooth authentication with the XBee device.
+ ///
+ /// If there is any error performing the
+ /// bluetooth authentication.
+ /// If the connection interface is not open.
+ /// If there is any error in the communication process.
+ public void Authenticate()
+ {
+ // Check connection.
+ if (!device.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ device.PacketReceived += ReceiveBLEPacket;
+
+ try
+ {
+ User user = new User(API_USERNAME, password);
+
+ // Phase 1.
+ byte[] clientEphemeral = user.StartAuthentication();
+ expectedPhase = SrpPhase.PHASE_2;
+ unlockResponse = null;
+ device.SendPacketAsync(new BluetoothUnlockPacket(SrpPhase.PHASE_1, clientEphemeral));
+ lock (unlockLock)
+ {
+ Monitor.Wait(unlockLock, TIMEOUT_AUTH);
+ }
+ CheckResponsePacket();
+
+ // Phase 2.
+ int index = 0;
+ byte[] salt = new byte[LENGTH_SALT];
+ Array.Copy(unlockResponse.Data, index, salt, 0, salt.Length);
+ index += LENGTH_SALT;
+ byte[] serverEphemeral = new byte[LENGTH_EPHEMERAL];
+ Array.Copy(unlockResponse.Data, index, serverEphemeral, 0, serverEphemeral.Length);
+
+ // Phase 3.
+ byte[] clientSessionProof = user.ProcessChallenge(salt, serverEphemeral);
+ expectedPhase = SrpPhase.PHASE_4;
+ unlockResponse = null;
+ device.SendPacketAsync(new BluetoothUnlockPacket(SrpPhase.PHASE_3, clientSessionProof));
+ lock (unlockLock)
+ {
+ Monitor.Wait(unlockLock, TIMEOUT_AUTH);
+ }
+ CheckResponsePacket();
+
+ // Phase 4.
+ index = 0;
+ byte[] serverSessionProof = new byte[LENGTH_SESSION_PROOF];
+ Array.Copy(unlockResponse.Data, index, serverSessionProof, 0, serverSessionProof.Length);
+ index += LENGTH_SESSION_PROOF;
+ TxNonce = new byte[LENGTH_NONCE];
+ Array.Copy(unlockResponse.Data, index, TxNonce, 0, TxNonce.Length);
+ index += LENGTH_NONCE;
+ RxNonce = new byte[LENGTH_NONCE];
+ Array.Copy(unlockResponse.Data, index, RxNonce, 0, RxNonce.Length);
+
+ user.VerifySession(serverSessionProof);
+
+ if (!user.authenticated)
+ throw new BluetoothAuthenticationException(string.Format(ERROR_AUTH_EXTENDED, ERROR_BAD_PROOF));
+
+ // Save the sesion key.
+ Key = user.SessionKey;
+ }
+ catch (IOException e)
+ {
+ throw new XBeeException(ERROR_WRITING, e);
+ }
+ finally
+ {
+ device.PacketReceived -= ReceiveBLEPacket;
+ }
+ }
+
+ ///
+ /// Checks the unlock response packet and throws the appropriate exception in case of error.
+ ///
+ /// If the unlock response is null
+ /// or if the SRP Phase value of the unlock response is
+ private void CheckResponsePacket()
+ {
+ if (unlockResponse == null)
+ throw new BluetoothAuthenticationException(string.Format(ERROR_AUTH_EXTENDED, ERROR_RESPONSE_NOT_RECEIVED));
+ else if (unlockResponse.SrpPhase == SrpPhase.UNKNOWN)
+ throw new BluetoothAuthenticationException(string.Format(ERROR_AUTH_EXTENDED, unlockResponse.SrpError.GetName()));
+ }
+
+ ///
+ /// Callback called after a is received and the
+ /// corresponding Packet Received event has been fired.
+ ///
+ /// The object that sent the event.
+ /// The Packet Received event.
+ ///
+ private void ReceiveBLEPacket(object sender, PacketReceivedEventArgs e)
+ {
+ if (!(e.ReceivedPacket is XBeeAPIPacket) || ((XBeeAPIPacket)e.ReceivedPacket).FrameType != APIFrameType.BLE_UNLOCK_RESPONSE)
+ return;
+
+ BluetoothUnlockResponsePacket response = (BluetoothUnlockResponsePacket)e.ReceivedPacket;
+
+ // Check if the packet contains the expected phase or an error.
+ if (response.SrpPhase != SrpPhase.UNKNOWN && response.SrpPhase != expectedPhase)
+ return;
+
+ unlockResponse = response;
+
+ // Continue execution by notifying the lock object.
+ lock (unlockLock)
+ {
+ Monitor.Pulse(unlockLock);
+ }
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/CellularDevice.cs b/XBeeLibrary.Core/CellularDevice.cs
new file mode 100644
index 0000000..fc4edc3
--- /dev/null
+++ b/XBeeLibrary.Core/CellularDevice.cs
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Connection;
+using XBeeLibrary.Core.Events;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.Models;
+using XBeeLibrary.Core.Packet;
+using XBeeLibrary.Core.Packet.Cellular;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// This class represents a local Cellular device.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public class CellularDevice : IPDevice
+ {
+ ///
+ /// Class constructor. Instantiates a new object with the given
+ /// connection interface.
+ ///
+ /// The connection interface with the physical
+ /// Cellular device.
+ /// If == null.
+ ///
+ ///
+ ///
+ public CellularDevice(IConnectionInterface connectionInterface)
+ : base(connectionInterface) { }
+
+ // Events.
+ ///
+ /// Represents the method that will handle the SMS received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler SMSReceived
+ {
+ add
+ {
+ base.SMSReceived += value;
+ }
+ remove
+ {
+ base.SMSReceived -= value;
+ }
+ }
+
+ // Properties.
+ ///
+ /// The protocol of the XBee device.
+ ///
+ ///
+ public override XBeeProtocol XBeeProtocol => XBeeProtocol.CELLULAR;
+
+ ///
+ /// The IMEI address for this Cellular device.
+ ///
+ ///
+ public XBeeIMEIAddress IMEIAddress { get; private set; }
+
+ ///
+ /// The 64-bit address of this XBee device. This is not supported in Cellular
+ /// devices, so it always returns null.
+ ///
+ ///
+ public override XBee64BitAddress XBee64BitAddr
+ {
+ get
+ {
+ // Cellular protocol does not have 64-bit address.
+ return null;
+ }
+ }
+
+ ///
+ /// The node identifier of this XBee device. This is not supported in Cellular
+ /// devices, so it always returns null.
+ ///
+ ///
+ public override string NodeID
+ {
+ get
+ {
+ // Cellular protocol does not have Node Identifier.
+ return null;
+ }
+ }
+
+ ///
+ /// Opens the connection interface associated with this XBee device.
+ ///
+ /// When opening the device an information reading process is automatically performed.
+ /// This includes:
+ ///
+ /// - 64-bit address.
+ /// - Node Identifier.
+ /// - Hardware version
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - 16-bit address (not for DigiMesh modules).
+ ///
+ /// If this device connection is already open.
+ /// If the operating mode of the device is
+ /// or
+ /// If the BLE authentication process fails.
+ /// If the timeout to read settings when initializing the
+ /// device elapses without response.
+ /// If there is any problem opening this device connection.
+ ///
+ ///
+ public override void Open()
+ {
+ base.Open();
+ if (XBeeProtocol != XBeeProtocol.CELLULAR)
+ throw new XBeeDeviceException("XBee device is not a " + XBeeProtocol.CELLULAR.GetDescription()
+ + " device, it is a " + XBeeProtocol.GetDescription() + " device.");
+ }
+
+ ///
+ /// Reads some parameters from this device and obtains its protocol.
+ ///
+ /// This method refresh the values of:
+ ///
+ /// - 64-bit address only if it is not initialized.
+ /// - Node Identifier.
+ /// - Hardware version if it is not initialized.
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - IP address.
+ /// - IMEI address.
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout reading the parameters.
+ /// If there is any other XBee related error.
+ public override void ReadDeviceInfo()
+ {
+ base.ReadDeviceInfo();
+ IMEIAddress = new XBeeIMEIAddress(XBee64BitAddr.Value);
+ }
+
+ ///
+ /// Returns the current association status of this Cellular device.
+ ///
+ /// It indicates occurrences of errors during the modem initialization and connection.
+ /// The current of the device.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the cellular association
+ /// indication status.
+ /// If there is any other XBee related error.
+ ///
+ public CellularAssociationIndicationStatus GetCellularAssociationIndicationStatus()
+ {
+ byte[] associationIndicationValue = GetParameter("AI");
+ return CellularAssociationIndicationStatus.UNKNOWN.Get(ByteUtils.ByteArrayToInt(associationIndicationValue));
+ }
+
+ ///
+ /// Indicates whether the device is connected to the Internet or not.
+ ///
+ /// true if the device is connected to the Internet, false otherwise.
+ /// If this device connection is not open.
+ /// If there is a timeout reading the cellular association
+ /// indication status.
+ /// If there is any other XBee related error.
+ public bool IsConnected()
+ {
+ return GetCellularAssociationIndicationStatus() == CellularAssociationIndicationStatus.SUCCESSFULLY_CONNECTED;
+ }
+
+ ///
+ /// Sends the provided SMS message to the given phone number.
+ ///
+ /// This method blocks till a success or error response arrives or the configured
+ /// receive timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ ///
+ /// For non-blocking operations use the method .
+ ///
+ /// The phone number to send the SMS to.
+ /// String containing the text of the SMS.
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote (remote devices
+ /// cannot send SMS).
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the received packet is not an instance of
+ ///
+ /// or if its transmit status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public void SendSMS(string phoneNumber, string data)
+ {
+ if (phoneNumber == null)
+ throw new ArgumentNullException("Phone number cannot be null");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send SMS from a remote device.");
+
+ logger.Debug(ToString() + "Sending SMS to " + phoneNumber + " >> " + data + ".");
+ XBeePacket xbeePacket = new TXSMSPacket(GetNextFrameID(), phoneNumber, data);
+ SendAndCheckXBeePacket(xbeePacket, false);
+ }
+
+ ///
+ /// Sends asynchronously the provided SMS to the given phone number.
+ ///
+ /// Asynchronous transmissions do not wait for answer or for transmit status packet.
+ /// The phone number to send the SMS to.
+ /// String containing the text of the SMS.
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote (remote devices
+ /// cannot send SMS).
+ /// If there is any other XBee related error.
+ ///
+ public void SendSMSAsync(string phoneNumber, string data)
+ {
+ if (phoneNumber == null)
+ throw new ArgumentNullException("Phone number cannot be null");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ // Check if device is remote.
+ if (IsRemote)
+ throw new OperationNotSupportedException("Cannot send SMS from a remote device.");
+
+ logger.Debug(ToString() + "Sending SMS asynchronously to " + phoneNumber + " >> " + data + ".");
+ XBeePacket xbeePacket = new TXSMSPacket(GetNextFrameID(), phoneNumber, data);
+ SendAndCheckXBeePacket(xbeePacket, true);
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Connection/ConnectionType.cs b/XBeeLibrary.Core/Connection/ConnectionType.cs
new file mode 100644
index 0000000..9381b04
--- /dev/null
+++ b/XBeeLibrary.Core/Connection/ConnectionType.cs
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Connection
+{
+ ///
+ /// This enumeration lists all the available connections used to communicate with XBee devices.
+ ///
+ public enum ConnectionType : byte
+ {
+ SERIAL = 0x00,
+ BLUETOOTH = 0x01,
+ UNKNOWN = 0xFE
+ }
+
+ public static class ConnectionTypeExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static ConnectionTypeExtensions()
+ {
+ lookupTable.Add(ConnectionType.SERIAL, "Serial connection");
+ lookupTable.Add(ConnectionType.BLUETOOTH, "Bluetooth connection");
+ }
+
+ ///
+ /// Gets the associated with the specified ID .
+ ///
+ ///
+ /// ID value to retrieve .
+ /// The for the specified ID ,
+ /// if it does not exist.
+ public static ConnectionType Get(this ConnectionType dumb, byte value)
+ {
+ var values = Enum.GetValues(typeof(ConnectionType)).OfType();
+
+ if (values.Cast().Contains(value))
+ return (ConnectionType)value;
+
+ return ConnectionType.UNKNOWN;
+ }
+
+ ///
+ /// Gets the connection type value.
+ ///
+ ///
+ /// The connection type value.
+ public static byte GetValue(this ConnectionType source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the connection type name.
+ ///
+ ///
+ /// The connection type name.
+ public static string GetName(this ConnectionType source)
+ {
+ return lookupTable.ContainsKey(source) ? lookupTable[source] : source.ToString();
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this ConnectionType source)
+ {
+ return string.Format("({0}) {1}", HexUtils.ByteArrayToHexString(ByteUtils.IntToByteArray((byte)source)), GetName(source));
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Connection/DataReader.cs b/XBeeLibrary.Core/Connection/DataReader.cs
new file mode 100644
index 0000000..0b051d7
--- /dev/null
+++ b/XBeeLibrary.Core/Connection/DataReader.cs
@@ -0,0 +1,988 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using Common.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using XBeeLibrary.Core.Events;
+using XBeeLibrary.Core.Events.Relay;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.IO;
+using XBeeLibrary.Core.Models;
+using XBeeLibrary.Core.Packet;
+using XBeeLibrary.Core.Packet.Cellular;
+using XBeeLibrary.Core.Packet.Common;
+using XBeeLibrary.Core.Packet.IP;
+using XBeeLibrary.Core.Packet.Raw;
+using XBeeLibrary.Core.Packet.Relay;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Connection
+{
+ ///
+ /// Thread that constantly reads data from an input stream.
+ ///
+ /// Depending on the XBee operating mode, read data is notified as is to the subscribed
+ /// listeners or is parsed to a packet using the packet parser and then notified to subscribed
+ /// listeners.
+ public class DataReader
+ {
+ // Constants.
+ private const int ALL_FRAME_IDS = 99999;
+ private const int MAXIMUM_PARALLEL_LISTENER_THREADS = 20;
+
+ // Variables.
+ private IConnectionInterface connectionInterface;
+
+ private volatile OperatingMode mode;
+
+ // It is required to keep a list of CustomPacketReceiveEventHandler objects. Each of those
+ // contains a Packet Received event handler and a frame ID associated with it. This means
+ // that each handler registered here will only respond to events associated with the correct
+ // Frame ID. When it is 99999 (ALL_FRAME_IDS), all the packets will be handled.
+ private List packetReceivedHandlers = new List();
+
+ private ILog logger;
+
+ private XBeePacketParser parser;
+ private AbstractXBeeDevice xbeeDevice;
+
+ private Task task;
+
+ ///
+ /// Class constructor. Instantiates a new object for the given connection
+ /// interface using the given XBee operating mode and XBee device.
+ ///
+ /// Connection interface to read data from.
+ /// XBee operating mode.
+ /// Reference to the XBee device containing this
+ /// object.
+ /// If == null.
+ ///
+ ///
+ ///
+ public DataReader(IConnectionInterface connectionInterface, OperatingMode mode, AbstractXBeeDevice xbeeDevice)
+ {
+ this.connectionInterface = connectionInterface ?? throw new ArgumentNullException("Connection interface cannot be null.");
+ this.mode = mode;
+ this.xbeeDevice = xbeeDevice;
+ logger = LogManager.GetLogger();
+ parser = new XBeePacketParser();
+ XBeePacketsQueue = new XBeePacketsQueue();
+
+ // Create the task.
+ task = new Task(() => { Run(); }, TaskCreationOptions.LongRunning);
+ }
+
+ // Events.
+ ///
+ /// Represents the method that will handle the data received event.
+ ///
+ ///
+ public event EventHandler DataReceived;
+
+ ///
+ /// Represents the method that will handle the packet received event.
+ ///
+ ///
+ public event EventHandler XBeePacketReceived;
+
+ ///
+ /// Represents the method that will handle the IO sample packet received event.
+ ///
+ ///
+ public event EventHandler IOSampleReceived;
+
+ ///
+ /// Represents the method that will handle the Modem status event.
+ ///
+ ///
+ public event EventHandler ModemStatusReceived;
+
+ ///
+ /// Represents the method that will handle the explicit data received event.
+ ///
+ ///
+ public event EventHandler ExplicitDataReceived;
+
+ ///
+ /// Represents the method that will handle the User Data Relay received event.
+ ///
+ ///
+ public event EventHandler UserDataRelayReceived;
+
+ ///
+ /// Represents the method that will handle the Bluetooth data received event.
+ ///
+ ///
+ public event EventHandler BluetoothDataReceived;
+
+ ///
+ /// Represents the method that will handle the MicroPython data received event.
+ ///
+ ///
+ public event EventHandler MicroPythonDataReceived;
+
+ ///
+ /// Represents the method that will handle the serial data received event.
+ ///
+ ///
+ public event EventHandler SerialDataReceived;
+
+ ///
+ /// Represents the method that will handle the SMS received event.
+ ///
+ ///
+ public event EventHandler SMSReceived;
+
+ ///
+ /// Represents the method that will handle the IP data received event.
+ ///
+ ///
+ public event EventHandler IPDataReceived;
+
+ // Properties.
+ ///
+ /// Indicates whether the data reader is running or not.
+ ///
+ public bool IsRunning { get; private set; } = false;
+
+ ///
+ /// Returns the queue of read XBee packets.
+ ///
+ /// The queue of read XBee packets.
+ ///
+ public XBeePacketsQueue XBeePacketsQueue { get; }
+
+ ///
+ /// Sets the XBee operating mode of this data reader.
+ ///
+ /// The new xBee operating mode.
+ ///
+ public void SetXBeeReaderMode(OperatingMode mode)
+ {
+ this.mode = mode;
+ }
+
+ ///
+ /// Returns the remote XBee device from where the given package was sent from.
+ ///
+ /// This is for internal use only.
+ ///
+ /// If the package does not contain information about the source, this method returns null
+ /// (for example, ).
+ ///
+ /// First the device that sent the provided package is looked in the network of the local
+ /// XBee device. If the remote device is not in the network, it is automatically added only
+ /// if the packet contains information about the origin of the package.
+ /// The packet sent from the remote device.
+ /// The remote XBee device that sends the given packet. It may be null if the
+ /// packet is not a known frame () or if it does not contain information
+ /// of the source device.
+ /// If == null.
+ /// If any error occurred while adding the device to the
+ /// network.
+ public RemoteXBeeDevice GetRemoteXBeeDeviceFromPacket(XBeeAPIPacket apiPacket)
+ {
+ if (apiPacket == null)
+ throw new ArgumentNullException("XBee API packet cannot be null.");
+
+ APIFrameType apiType = apiPacket.FrameType;
+
+ RemoteXBeeDevice remoteDevice = null;
+ XBee64BitAddress addr64 = null;
+ XBee16BitAddress addr16 = null;
+
+ XBeeNetwork network = xbeeDevice.GetNetwork();
+
+ switch (apiType)
+ {
+ case APIFrameType.RECEIVE_PACKET:
+ ReceivePacket receivePacket = (ReceivePacket)apiPacket;
+ addr64 = receivePacket.SourceAddress64;
+ addr16 = receivePacket.SourceAddress16;
+ if (!addr64.Equals(XBee64BitAddress.UNKNOWN_ADDRESS))
+ remoteDevice = network.GetDevice(addr64);
+ else if (!addr16.Equals(XBee16BitAddress.UNKNOWN_ADDRESS))
+ remoteDevice = network.GetDevice(addr16);
+ break;
+ case APIFrameType.RX_64:
+ RX64Packet rx64Packet = (RX64Packet)apiPacket;
+ addr64 = rx64Packet.SourceAddress64;
+ remoteDevice = network.GetDevice(addr64);
+ break;
+ case APIFrameType.RX_16:
+ RX16Packet rx16Packet = (RX16Packet)apiPacket;
+ addr64 = XBee64BitAddress.UNKNOWN_ADDRESS;
+ addr16 = rx16Packet.SourceAddress16;
+ remoteDevice = network.GetDevice(addr16);
+ break;
+ case APIFrameType.IO_DATA_SAMPLE_RX_INDICATOR:
+ IODataSampleRxIndicatorPacket ioSamplePacket = (IODataSampleRxIndicatorPacket)apiPacket;
+ addr64 = ioSamplePacket.SourceAddress64;
+ addr16 = ioSamplePacket.SourceAddress16;
+ remoteDevice = network.GetDevice(addr64);
+ break;
+ case APIFrameType.RX_IO_64:
+ RX64IOPacket rx64IOPacket = (RX64IOPacket)apiPacket;
+ addr64 = rx64IOPacket.SourceAddress64;
+ remoteDevice = network.GetDevice(addr64);
+ break;
+ case APIFrameType.RX_IO_16:
+ RX16IOPacket rx16IOPacket = (RX16IOPacket)apiPacket;
+ addr64 = XBee64BitAddress.UNKNOWN_ADDRESS;
+ addr16 = rx16IOPacket.SourceAddress16;
+ remoteDevice = network.GetDevice(addr16);
+ break;
+ case APIFrameType.EXPLICIT_RX_INDICATOR:
+ ExplicitRxIndicatorPacket explicitDataPacket = (ExplicitRxIndicatorPacket)apiPacket;
+ addr64 = explicitDataPacket.SourceAddress64;
+ addr16 = explicitDataPacket.SourceAddress16;
+ remoteDevice = network.GetDevice(addr64);
+ break;
+ default:
+ // Rest of the types are considered not to contain information
+ // about the origin of the packet.
+ return remoteDevice;
+ }
+
+ // If the origin is not in the network, add it.
+ if (remoteDevice == null)
+ {
+ remoteDevice = CreateRemoteXBeeDevice(addr64, addr16, null);
+ if (!addr64.Equals(XBee64BitAddress.UNKNOWN_ADDRESS) || !addr16.Equals(XBee16BitAddress.UNKNOWN_ADDRESS))
+ network.AddRemoteDevice(remoteDevice);
+ }
+
+ return remoteDevice;
+ }
+
+ ///
+ /// Stops the data reader thread.
+ ///
+ public void StopReader()
+ {
+ IsRunning = false;
+ lock (connectionInterface)
+ {
+ Monitor.Pulse(connectionInterface);
+ }
+ logger.Debug(connectionInterface.ToString() + "Data reader stopped.");
+ }
+
+ ///
+ /// Adds the given to the list of event
+ /// handlers that will be notified whenever a packet associated to the frame ID of
+ /// is received.
+ ///
+ /// The handler to be notified when a packet is received.
+ ///
+ ///
+ ///
+ internal void AddPacketReceivedHandler(EventHandler handler)
+ {
+ lock (packetReceivedHandlers)
+ {
+ packetReceivedHandlers.Add(new CustomPacketReceivedEventHandler(handler));
+ XBeePacketReceived += handler;
+ }
+ }
+
+ ///
+ /// Adds the given to the list of event handlers
+ /// that will be notified whenever a packet associated to the frame ID of
+ /// is received.
+ ///
+ /// The handler to be notified when a packet is received.
+ /// The frame ID associated with the handler.
+ ///
+ ///
+ ///
+ internal void AddPacketReceivedHandler(EventHandler handler, int frameId)
+ {
+ lock (packetReceivedHandlers)
+ {
+ packetReceivedHandlers.Add(new CustomPacketReceivedEventHandler(handler, frameId));
+ XBeePacketReceived += handler;
+ }
+ }
+
+ ///
+ /// Removes the given from the list of packet
+ /// received event handlers.
+ ///
+ /// The handler to be removed.
+ ///
+ ///
+ ///
+ internal void RemovePacketReceivedHandler(EventHandler handler)
+ {
+ lock (packetReceivedHandlers)
+ {
+ // Search the handler in the list.
+ foreach (CustomPacketReceivedEventHandler customHandler in packetReceivedHandlers)
+ {
+ if (customHandler.Handler.Equals(handler))
+ {
+ packetReceivedHandlers.Remove(customHandler);
+ XBeePacketReceived -= handler;
+ return;
+ }
+ }
+ }
+ }
+
+ internal void Start()
+ {
+ task.Start();
+ }
+
+ private void Run()
+ {
+ logger.Debug(connectionInterface.ToString() + "Data reader started.");
+ IsRunning = true;
+ // Clear the list of read packets.
+ XBeePacketsQueue.ClearQueue();
+ try
+ {
+ lock (connectionInterface)
+ {
+ Monitor.Wait(connectionInterface);
+ }
+ while (IsRunning)
+ {
+ if (!IsRunning)
+ break;
+ if (connectionInterface.Stream != null)
+ {
+ switch (mode)
+ {
+ case OperatingMode.AT:
+ break;
+ case OperatingMode.API:
+ case OperatingMode.API_ESCAPE:
+ int headerByte = connectionInterface.Stream.ReadByte();
+ // If it is packet header parse the packet, if not discard this byte and continue.
+ if (headerByte == SpecialByte.HEADER_BYTE.GetValue())
+ {
+ try
+ {
+ XBeePacket packet = parser.ParsePacket(connectionInterface.Stream, mode);
+ PacketReceived(packet);
+ }
+ catch (InvalidPacketException e)
+ {
+ logger.Error("Error parsing the API packet.", e);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else if (connectionInterface.Stream == null)
+ break;
+ if (connectionInterface.Stream == null)
+ break;
+ else if (connectionInterface.Stream.Available > 0)
+ continue;
+ lock (connectionInterface)
+ {
+ Monitor.Wait(connectionInterface);
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ logger.Error("Error reading from input stream.", e);
+ }
+ finally
+ {
+ if (IsRunning)
+ {
+ IsRunning = false;
+ if (connectionInterface.IsOpen)
+ connectionInterface.Close();
+ }
+ }
+ }
+
+ ///
+ /// Dispatches the received XBee packet to the corresponding event handler(s).
+ ///
+ /// The received XBee packet to be dispatched to the corresponding event
+ /// handlers.
+ ///
+ ///
+ private void PacketReceived(XBeePacket packet)
+ {
+ // Add the packet to the packets queue.
+ XBeePacketsQueue.AddPacket(packet);
+ // Notify that a packet has been received to the corresponding event handlers.
+ NotifyPacketReceived(packet);
+
+ // Check if the packet is an API packet.
+ if (!(packet is XBeeAPIPacket))
+ return;
+
+ // Get the API packet type.
+ XBeeAPIPacket apiPacket = (XBeeAPIPacket)packet;
+ APIFrameType apiType = apiPacket.FrameType;
+
+ try
+ {
+ // Obtain the remote device from the packet.
+ RemoteXBeeDevice remoteDevice = GetRemoteXBeeDeviceFromPacket(apiPacket);
+ byte[] data = null;
+
+ switch (apiType)
+ {
+ case APIFrameType.RECEIVE_PACKET:
+ ReceivePacket receivePacket = (ReceivePacket)apiPacket;
+ data = receivePacket.RFData;
+ NotifyDataReceived(new XBeeMessage(remoteDevice, data, apiPacket.IsBroadcast));
+ break;
+ case APIFrameType.RX_64:
+ RX64Packet rx64Packet = (RX64Packet)apiPacket;
+ data = rx64Packet.RFData;
+ NotifyDataReceived(new XBeeMessage(remoteDevice, data, apiPacket.IsBroadcast));
+ break;
+ case APIFrameType.RX_16:
+ RX16Packet rx16Packet = (RX16Packet)apiPacket;
+ data = rx16Packet.RFData;
+ NotifyDataReceived(new XBeeMessage(remoteDevice, data, apiPacket.IsBroadcast));
+ break;
+ case APIFrameType.IO_DATA_SAMPLE_RX_INDICATOR:
+ IODataSampleRxIndicatorPacket ioSamplePacket = (IODataSampleRxIndicatorPacket)apiPacket;
+ NotifyIOSampleReceived(remoteDevice, ioSamplePacket.IOSample);
+ break;
+ case APIFrameType.RX_IO_64:
+ RX64IOPacket rx64IOPacket = (RX64IOPacket)apiPacket;
+ NotifyIOSampleReceived(remoteDevice, rx64IOPacket.IoSample);
+ break;
+ case APIFrameType.RX_IO_16:
+ RX16IOPacket rx16IOPacket = (RX16IOPacket)apiPacket;
+ NotifyIOSampleReceived(remoteDevice, rx16IOPacket.IoSample);
+ break;
+ case APIFrameType.MODEM_STATUS:
+ ModemStatusPacket modemStatusPacket = (ModemStatusPacket)apiPacket;
+ NotifyModemStatusReceived(modemStatusPacket.Status);
+ break;
+ case APIFrameType.EXPLICIT_RX_INDICATOR:
+ ExplicitRxIndicatorPacket explicitDataPacket = (ExplicitRxIndicatorPacket)apiPacket;
+ byte sourceEndpoint = explicitDataPacket.SourceEndpoint;
+ byte destEndpoint = explicitDataPacket.DestEndpoint;
+ byte[] clusterID = explicitDataPacket.ClusterID;
+ byte[] profileID = explicitDataPacket.ProfileID;
+ data = explicitDataPacket.RFData;
+ // If this is an explicit packet for data transmissions in the Digi profile,
+ // notify also the data event handler and add a Receive packet to the queue.
+ if (sourceEndpoint == ExplicitRxIndicatorPacket.DATA_ENDPOINT &&
+ destEndpoint == ExplicitRxIndicatorPacket.DATA_ENDPOINT &&
+ clusterID.SequenceEqual(ExplicitRxIndicatorPacket.DATA_CLUSTER) &&
+ profileID.SequenceEqual(ExplicitRxIndicatorPacket.DIGI_PROFILE))
+ {
+ NotifyDataReceived(new XBeeMessage(remoteDevice, data, apiPacket.IsBroadcast));
+ XBeePacketsQueue.AddPacket(new ReceivePacket(explicitDataPacket.SourceAddress64,
+ explicitDataPacket.SourceAddress16,
+ explicitDataPacket.ReceiveOptions,
+ explicitDataPacket.RFData));
+ }
+ NotifyExplicitDataReceived(new ExplicitXBeeMessage(remoteDevice, sourceEndpoint, destEndpoint, clusterID,
+ profileID, data, explicitDataPacket.IsBroadcast));
+ break;
+ case APIFrameType.USER_DATA_RELAY_OUTPUT:
+ UserDataRelayOutputPacket relayPacket = (UserDataRelayOutputPacket)apiPacket;
+ NotifyUserDataRelayReceived(new UserDataRelayMessage(relayPacket.SourceInterface, relayPacket.Data));
+ break;
+ case APIFrameType.RX_IPV4:
+ RXIPv4Packet rxIPv4Packet = (RXIPv4Packet)apiPacket;
+ NotifyIPDataReceived(new IPMessage(
+ rxIPv4Packet.SourceAddress,
+ rxIPv4Packet.SourcePort,
+ rxIPv4Packet.DestPort,
+ rxIPv4Packet.Protocol,
+ rxIPv4Packet.Data));
+ break;
+ case APIFrameType.RX_SMS:
+ RXSMSPacket rxSMSPacket = (RXSMSPacket)apiPacket;
+ NotifySMSReceived(new SMSMessage(rxSMSPacket.PhoneNumber, rxSMSPacket.Data));
+ break;
+ default:
+ break;
+ }
+
+ }
+ catch (XBeeException e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Creates a new remote XBee device with the provided 64-bit address, 16-bit address, node
+ /// identifier and the XBee device that is using this data reader as the connection interface
+ /// for the remote device.
+ ///
+ /// The new XBee device will be a ,
+ /// a , a or a
+ /// depending on the protocol of the local XBee device. If
+ /// the protocol cannot be determined or is unknown a will
+ /// be created instead.
+ /// The 64-bit address of the new remote device. It cannot be null.
+ /// The 16-bit address of the new remote device. It may be null.
+ /// The node identifier of the new remote device. It may be null.
+ /// A new remote XBee device with the given parameters.
+ private RemoteXBeeDevice CreateRemoteXBeeDevice(XBee64BitAddress addr64,
+ XBee16BitAddress addr16, string ni)
+ {
+ RemoteXBeeDevice device = null;
+
+ switch (xbeeDevice.XBeeProtocol)
+ {
+ case XBeeProtocol.ZIGBEE:
+ device = new RemoteZigBeeDevice(xbeeDevice, addr64, addr16, ni);
+ break;
+ case XBeeProtocol.DIGI_MESH:
+ device = new RemoteDigiMeshDevice(xbeeDevice, addr64, ni);
+ break;
+ case XBeeProtocol.DIGI_POINT:
+ device = new RemoteDigiPointDevice(xbeeDevice, addr64, ni);
+ break;
+ case XBeeProtocol.RAW_802_15_4:
+ device = new RemoteRaw802Device(xbeeDevice, addr64, addr16, ni);
+ break;
+ default:
+ device = new RemoteXBeeDevice(xbeeDevice, addr64, addr16, ni);
+ break;
+ }
+
+ return device;
+ }
+
+ ///
+ /// Notifies subscribed data receive listeners that a new XBee data packet has been received
+ /// in form of an .
+ ///
+ /// The XBee message to be sent to subscribed XBee data listeners.
+ ///
+ private void NotifyDataReceived(XBeeMessage xbeeMessage)
+ {
+ if (DataReceived == null)
+ return;
+
+ if (xbeeMessage.IsBroadcast)
+ logger.InfoFormat(connectionInterface.ToString() + "Broadcast data received from {0} >> {1}.",
+ xbeeMessage.Device.XBee64BitAddr, HexUtils.PrettyHexString(xbeeMessage.Data));
+ else
+ logger.InfoFormat(connectionInterface.ToString() + "Data received from {0} >> {1}.",
+ xbeeMessage.Device.XBee64BitAddr, HexUtils.PrettyHexString(xbeeMessage.Data));
+
+ try
+ {
+ lock (DataReceived)
+ {
+ var handler = DataReceived;
+ if (handler != null)
+ {
+ var args = new DataReceivedEventArgs(xbeeMessage);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Notifies subscribed XBee packet event handlers that a new XBee Packet has been received.
+ ///
+ /// The received XBee packet.
+ ///
+ ///
+ private void NotifyPacketReceived(XBeePacket packet)
+ {
+ logger.DebugFormat(connectionInterface.ToString() + "Packet received: \n{0}", packet.ToPrettyString());
+
+ try
+ {
+ lock (packetReceivedHandlers)
+ {
+ var args = new PacketReceivedEventArgs(packet);
+ XBeeAPIPacket apiPacket = (XBeeAPIPacket)packet;
+ List handlersToRemove = new List();
+
+ // Need to go over the list of Packet received handlers to
+ // verify which ones need to be notified of the received packet.
+ foreach (var packetHandler in packetReceivedHandlers)
+ {
+ if (packetHandler.Handler != null)
+ {
+ if (packetHandler.FrameId == ALL_FRAME_IDS)
+ packetHandler.Handler.DynamicInvoke(this, args);
+ else if (apiPacket.NeedsAPIFrameID
+ && apiPacket.FrameID == packetHandler.FrameId)
+ {
+ packetHandler.Handler.DynamicInvoke(this, args);
+ handlersToRemove.Add(packetHandler);
+ }
+ }
+ }
+ foreach (CustomPacketReceivedEventHandler handlerToRemove in handlersToRemove)
+ RemovePacketReceivedHandler(handlerToRemove.Handler);
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Notifies subscribed IO sample listeners that a new IO sample packet has been received.
+ ///
+ /// The remote XBee device that sent the sample.
+ /// The received IO sample.
+ ///
+ ///
+ private void NotifyIOSampleReceived(RemoteXBeeDevice remoteDevice, IOSample ioSample)
+ {
+ logger.Debug(connectionInterface.ToString() + " IO sample received.");
+
+ if (IOSampleReceived == null)
+ return;
+
+ try
+ {
+ lock (IOSampleReceived)
+ {
+ var handler = IOSampleReceived;
+ if (handler != null)
+ {
+ var args = new IOSampleReceivedEventArgs(remoteDevice, ioSample);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Notifies subscribed Modem Status listeners that a Modem Status event packet has been received.
+ ///
+ /// The Modem Status event.
+ ///
+ private void NotifyModemStatusReceived(ModemStatusEvent modemStatusEvent)
+ {
+ logger.Debug(connectionInterface.ToString() + "Modem Status event received.");
+
+ try
+ {
+ lock (ModemStatusReceived)
+ {
+ var handler = ModemStatusReceived;
+ if (handler != null)
+ {
+ var args = new ModemStatusReceivedEventArgs(modemStatusEvent);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Notifies subscribed explicit data receive listeners that a new XBee explicit data packet has been
+ /// received in form of an .
+ ///
+ /// The XBee message to be sent to subscribed XBee data listeners.
+ ///
+ private void NotifyExplicitDataReceived(ExplicitXBeeMessage explicitXBeeMessage)
+ {
+ if (ExplicitDataReceived == null)
+ return;
+
+ if (explicitXBeeMessage.IsBroadcast)
+ {
+ logger.InfoFormat(connectionInterface.ToString() + "Broadcast explicit data received from {0} >> {1}.",
+ explicitXBeeMessage.Device.XBee64BitAddr, HexUtils.PrettyHexString(explicitXBeeMessage.Data));
+ }
+ else
+ {
+ logger.InfoFormat(connectionInterface.ToString() + "Explicit data received from {0} >> {1}.",
+ explicitXBeeMessage.Device.XBee64BitAddr, HexUtils.PrettyHexString(explicitXBeeMessage.Data));
+ }
+
+ try
+ {
+ lock (ExplicitDataReceived)
+ {
+ var handler = ExplicitDataReceived;
+ if (handler != null)
+ {
+ var args = new ExplicitDataReceivedEventArgs(explicitXBeeMessage);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Notifies subscribed User Data Relay receive listeners that a new packet has been received in
+ /// form of an .
+ ///
+ /// The User Data Relay message.
+ ///
+ private void NotifyUserDataRelayReceived(UserDataRelayMessage userDataRelayMessage)
+ {
+ logger.InfoFormat(connectionInterface.ToString() + " User Data Relay received from interface {0} >> {1}.",
+ userDataRelayMessage.SourceInterface.GetDescription(), HexUtils.PrettyHexString(userDataRelayMessage.Data));
+
+ // Notify generic event callbacks.
+ if (UserDataRelayReceived != null)
+ {
+ try
+ {
+ lock (UserDataRelayReceived)
+ {
+ var handler = UserDataRelayReceived;
+ if (handler != null)
+ {
+ var args = new UserDataRelayReceivedEventArgs(userDataRelayMessage);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ // Notify specific event callbacks depending on the interface.
+ try
+ {
+ switch (userDataRelayMessage.SourceInterface)
+ {
+ case XBeeLocalInterface.BLUETOOTH:
+ if (BluetoothDataReceived != null)
+ {
+ lock (BluetoothDataReceived)
+ {
+ var handler = BluetoothDataReceived;
+ if (handler != null)
+ {
+ var args = new BluetoothDataReceivedEventArgs(userDataRelayMessage.Data);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ break;
+ case XBeeLocalInterface.MICROPYTHON:
+ if (MicroPythonDataReceived != null)
+ {
+ lock (MicroPythonDataReceived)
+ {
+ var handler = MicroPythonDataReceived;
+ if (handler != null)
+ {
+ var args = new MicroPythonDataReceivedEventArgs(userDataRelayMessage.Data);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ break;
+ case XBeeLocalInterface.SERIAL:
+ if (SerialDataReceived != null)
+ {
+ lock (SerialDataReceived)
+ {
+ var handler = SerialDataReceived;
+ if (handler != null)
+ {
+ var args = new SerialDataReceivedEventArgs(userDataRelayMessage.Data);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Notifies subscribed SMS receive listeners that a new XBee SMS packet has been received
+ /// in form of an .
+ ///
+ /// The message to be sent to subscribed data listeners.
+ ///
+ private void NotifySMSReceived(SMSMessage smsMessage)
+ {
+ logger.InfoFormat(connectionInterface.ToString() + "SMS received from {0} >> {1}.",
+ smsMessage.PhoneNumber, smsMessage.Data);
+
+ try
+ {
+ lock (SMSReceived)
+ {
+ var handler = SMSReceived;
+ if (handler != null)
+ {
+ var args = new SMSReceivedEventArgs(smsMessage);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Notifies subscribed IP data receive listeners that a new XBee IP packet has been received
+ /// in form of an .
+ ///
+ /// The message to be sent to subscribed data listeners.
+ ///
+ private void NotifyIPDataReceived(IPMessage ipMessage)
+ {
+ logger.InfoFormat(connectionInterface.ToString() + " IP message received from {0} >> {1}.",
+ ipMessage.IPAddress, ipMessage.DataString);
+
+ try
+ {
+ lock (IPDataReceived)
+ {
+ var handler = IPDataReceived;
+ if (handler != null)
+ {
+ var args = new IPDataReceivedEventArgs(ipMessage);
+
+ handler.GetInvocationList().AsParallel().ForAll((action) =>
+ {
+ action.DynamicInvoke(this, args);
+ });
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ ///
+ /// Internal class to group a Packet Received Event Handler and a Frame ID. By default,if no Frame ID is
+ /// specified is assumed (handler associated to all incoming packets).
+ ///
+ internal class CustomPacketReceivedEventHandler
+ {
+ ///
+ /// Class Constructor. Instantiates a new
+ /// object for the given and associates it with all incoming packets.
+ ///
+ /// The packet received event handler.
+ public CustomPacketReceivedEventHandler(EventHandler handler)
+ {
+ Handler = handler;
+ }
+
+ ///
+ /// Class Constructor. Instantiates a new
+ /// object for the given and associates it with the
+ /// given .
+ ///
+ /// The packet received event handler.
+ /// The frame ID.
+ public CustomPacketReceivedEventHandler(EventHandler handler, int frameId)
+ {
+ Handler = handler;
+ FrameId = frameId;
+ }
+
+ ///
+ /// The Packet Received handler to associate to a frame ID.
+ ///
+ public EventHandler Handler { get; private set; }
+
+ ///
+ /// The Frame ID to associate to a Packet Receive handler. Default value of
+ /// to associate the handler to all incoming packets.
+ ///
+ public int FrameId { get; private set; } = ALL_FRAME_IDS;
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Connection/DataStream.cs b/XBeeLibrary.Core/Connection/DataStream.cs
new file mode 100644
index 0000000..618a8e9
--- /dev/null
+++ b/XBeeLibrary.Core/Connection/DataStream.cs
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.IO;
+
+namespace XBeeLibrary.Core.Connection
+{
+ public class DataStream : Stream
+ {
+ // Constants.
+ private static readonly int MAX_CAPACITY = 512 * 1024; // 512 Kb
+
+ // Variables.
+ private readonly MemoryStream innerStream;
+ private long readPosition;
+ private long writePosition;
+
+ public DataStream()
+ {
+ innerStream = new MemoryStream();
+ }
+
+ public DataStream(byte[] byteArray)
+ {
+ innerStream = new MemoryStream(byteArray);
+ writePosition = byteArray.Length;
+ }
+
+ // Properties.
+ public override bool CanRead { get { return true; } }
+
+ public override bool CanSeek { get { return false; } }
+
+ public override bool CanWrite { get { return true; } }
+
+ public override void Flush()
+ {
+ lock (innerStream)
+ {
+ innerStream.Flush();
+ }
+ }
+
+ public override long Length
+ {
+ get
+ {
+ lock (innerStream)
+ {
+ return innerStream.Length;
+ }
+ }
+ }
+
+ public int Available
+ {
+ get
+ {
+ return (int) (writePosition - readPosition);
+ }
+ }
+
+ public override long Position
+ {
+ get { return innerStream.Position; }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ lock (innerStream)
+ {
+ innerStream.Position = readPosition;
+ int read = innerStream.Read(buffer, offset, count);
+ readPosition = innerStream.Position;
+
+ return read;
+ }
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ lock (innerStream)
+ {
+ // If the stream length has reached the max capacity and all data has been read,
+ // reset the write and read positions.
+ if (writePosition > MAX_CAPACITY && writePosition == readPosition)
+ {
+ writePosition = 0;
+ readPosition = 0;
+ }
+
+ innerStream.Position = writePosition;
+ innerStream.Write(buffer, offset, count);
+ writePosition = innerStream.Position;
+ }
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Connection/IConnectionInterface.cs b/XBeeLibrary.Core/Connection/IConnectionInterface.cs
new file mode 100644
index 0000000..7264418
--- /dev/null
+++ b/XBeeLibrary.Core/Connection/IConnectionInterface.cs
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+namespace XBeeLibrary.Core.Connection
+{
+ ///
+ /// This interface represents a protocol independent connection with an XBee device.
+ ///
+ /// As an important point, the class implementing this interface must always notify
+ /// whenever new data is available to read. Not doing this will make the
+ /// class to wait forever for new data.
+ public interface IConnectionInterface
+ {
+ ///
+ /// Attempts to open the connection interface.
+ ///
+ ///
+ ///
+ void Open();
+
+ ///
+ /// Attempts to close the connection interface.
+ ///
+ ///
+ ///
+ void Close();
+
+ ///
+ /// Returns whether the connection interface is open or not.
+ ///
+ bool IsOpen { get; }
+
+ ///
+ /// Returns the connection interface stream to read and write data.
+ ///
+ ///
+ DataStream Stream { get; }
+
+ ///
+ /// Writes the given data in the connection interface.
+ ///
+ /// The data to be written in the connection interface.
+ ///
+ void WriteData(byte[] data);
+
+ ///
+ /// Writes the given data in the connection interface.
+ ///
+ /// The data to be written in the connection interface.
+ /// The start offset in the data to write.
+ /// The number of bytes to write.
+ ///
+ void WriteData(byte[] data, int offset, int length);
+
+ ///
+ /// Reads data from the connection interface and stores it in the provided byte array
+ /// returning the number of read bytes.
+ ///
+ /// The byte array to store the read data.
+ /// The number of bytes read.
+ ///
+ int ReadData(byte[] data);
+
+ ///
+ /// Reads the given number of bytes at the given offset from the connection interface and
+ /// stores it in the provided byte array returning the number of read bytes.
+ ///
+ /// The byte array to store the read data.
+ /// The start offset in data array at which the data is written.
+ /// Maximum number of bytes to read.
+ /// The number of bytes read.
+ ///
+ int ReadData(byte[] data, int offset, int length);
+
+ ///
+ /// Returns the connection type of this XBee interface.
+ ///
+ /// The connection type of this XBee interface.
+ ///
+ ConnectionType GetConnectionType();
+
+ ///
+ /// Sets the keys used for encryption and decryption.
+ ///
+ /// Encryption key.
+ /// Transmission nonce.
+ /// Reception nonce.
+ void SetEncryptionKeys(byte[] key, byte[] txNonce, byte[] rxNonce);
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/DigiMeshDevice.cs b/XBeeLibrary.Core/DigiMeshDevice.cs
new file mode 100644
index 0000000..7dac13b
--- /dev/null
+++ b/XBeeLibrary.Core/DigiMeshDevice.cs
@@ -0,0 +1,377 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Connection;
+using XBeeLibrary.Core.Events;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.Models;
+using XBeeLibrary.Core.Packet.Common;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// This class represents a local DigiMesh device.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public class DigiMeshDevice : XBeeDevice
+ {
+ ///
+ /// Class constructor. Instantiates a new object with the given
+ /// connection interface.
+ ///
+ /// The connection interface with the physical DigiMesh device.
+ /// If == null.
+ ///
+ ///
+ ///
+ public DigiMeshDevice(IConnectionInterface connectionInterface)
+ : base(connectionInterface) { }
+
+ // Events.
+ ///
+ /// Represents the method that will handle the explicit data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler ExplicitDataReceived
+ {
+ add
+ {
+ base.ExplicitDataReceived += value;
+ }
+ remove
+ {
+ base.ExplicitDataReceived -= value;
+ }
+ }
+
+ // Properties.
+ ///
+ /// The API output mode of the XBee device.
+ ///
+ /// The API output mode determines the format that the received data is output through the
+ /// serial interface of the XBee device.
+ /// If the returned value of the API Output Mode command
+ /// is null or empty.
+ ///
+ public new APIOutputMode APIOutputMode
+ {
+ get
+ {
+ return base.APIOutputMode;
+ }
+ set
+ {
+ base.APIOutputMode = value;
+ }
+ }
+
+ ///
+ /// The protocol of the XBee device.
+ ///
+ ///
+ public override XBeeProtocol XBeeProtocol => XBeeProtocol.DIGI_MESH;
+
+ ///
+ /// Opens the connection interface associated with this XBee device.
+ ///
+ /// When opening the device an information reading process is automatically performed.
+ /// This includes:
+ ///
+ /// - 64-bit address.
+ /// - Node Identifier.
+ /// - Hardware version
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - 16-bit address (not for DigiMesh modules).
+ ///
+ /// If this device connection is already open.
+ /// If the operating mode of the device is
+ /// or
+ /// If the BLE authentication process fails.
+ /// If the timeout to read settings when initializing the
+ /// device elapses without response.
+ /// If there is any problem opening this device connection.
+ ///
+ ///
+ public override void Open()
+ {
+ base.Open();
+
+ if (base.XBeeProtocol != XBeeProtocol.DIGI_MESH)
+ throw new XBeeDeviceException("XBee device is not a " + XBeeProtocol.DIGI_MESH.GetDescription()
+ + " device, it is a " + base.XBeeProtocol.GetDescription() + " device.");
+ }
+
+ ///
+ /// Returns the network associated with this XBee device.
+ ///
+ /// The XBee network of the device.
+ /// If this device connection is not open.
+ ///
+ ///
+ public override XBeeNetwork GetNetwork()
+ {
+ if (network == null)
+ network = new DigiMeshNetwork(this);
+ return network;
+ }
+
+ ///
+ /// Reads new explicit data received by this XBee device during the configured receive timeout.
+ ///
+ ///
+ /// This method blocks until new explicit data is received or the configured receive timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to .
+ ///
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this did not receive new explicit data during the configured receive timeout.
+ /// If the interface is not open.
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitData()
+ {
+ return base.ReadExplicitData();
+ }
+
+ ///
+ /// Reads new explicit data received by this XBee device during the configured receive timeout.
+ ///
+ ///
+ /// This method blocks until new explicit data is received or the configured receive timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to .
+ ///
+ /// The time to wait for new explicit data in milliseconds.
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this did not receive new explicit data during the configured receive timeout.
+ /// If 0.
+ /// If the interface is not open.
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitData(int timeout)
+ {
+ return base.ReadExplicitData(timeout);
+ }
+
+ ///
+ /// Reads new explicit data received from the given remote XBee device during the configured
+ /// receive timeout.
+ ///
+ ///
+ /// This method blocks until new explicit data from the provided remote XBee device is received
+ /// or the configured receive timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to .
+ ///
+ /// The remote device to read explicit data from.
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this device did not receive new explicit data from the provided remote XBee
+ /// device during the configured receive timeout.
+ /// If == null.
+ /// If the interface is not open.
+ ///
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice)
+ {
+ return base.ReadExplicitDataFrom(remoteXBeeDevice);
+ }
+
+ ///
+ /// Reads new explicit data received from the given remote XBee device during the provided timeout.
+ ///
+ ///
+ /// This method blocks until new explicit data from the provided remote XBee device is received
+ /// or the given timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to .
+ ///
+ /// The remote device to read explicit data from.
+ /// The time to wait for new explicit data in milliseconds.
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this device did not receive new data from the provided remote XBee device
+ /// during milliseconds.
+ /// If 0.
+ /// If == null.
+ /// If the interface is not open.
+ ///
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ return base.ReadExplicitDataFrom(remoteXBeeDevice, timeout);
+ }
+
+ ///
+ /// Sends asynchronously the provided data in application layer mode to the XBee device of the network
+ /// corresponding to the given 64-bit address. Application layer mode means that you need to specify
+ /// the application layer fields to be sent with the data.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for transmit
+ /// status packet.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ ///
+ ///
+ public new void SendExplicitDataAsync(XBee64BitAddress address, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitDataAsync(address, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends asynchronously the provided data in application layer mode to the provided XBee device choosing
+ /// the optimal send method depending on the protocol of the local XBee device. Application layer mode means
+ /// that you need to specify the application layer fields to be sent with the data.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for transmit status
+ /// packet.
+ /// The XBee device of the network that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ ///
+ ///
+ public new void SendExplicitDataAsync(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitDataAsync(remoteXBeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data in application layer mode to the XBee device of the network corresponding
+ /// to the given 64-bit address. Application layer mode means that you need to specify the application
+ /// layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive timeout
+ /// expires.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public new void SendExplicitData(XBee64BitAddress address, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitData(address, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data in application layer mode to the provided XBee device choosing the optimal
+ /// send method depending on the protocol of the local XBee device. Application layer mode means that you
+ /// need to specify the application layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive timeout
+ /// expires.
+ /// The XBee device of the network that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public new void SendExplicitData(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitData(remoteXBeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data to all the XBee nodes of the network (broadcast) in application layer mode.
+ /// Application layer mode means that you need to specify the application layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive timeout
+ /// expires.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ public new void SendBroadcastExplicitData(byte sourceEndpoint, byte destEndpoint, byte[] clusterID, byte[] profileID,
+ byte[] data)
+ {
+ base.SendBroadcastExplicitData(sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/DigiMeshNetwork.cs b/XBeeLibrary.Core/DigiMeshNetwork.cs
new file mode 100644
index 0000000..9374f4f
--- /dev/null
+++ b/XBeeLibrary.Core/DigiMeshNetwork.cs
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// This class represents a DigiMesh Network.
+ ///
+ /// The network allows the discovery of remote devices in the same network as the local one
+ /// and stores them.
+ ///
+ ///
+ ///
+ ///
+ public class DigiMeshNetwork : XBeeNetwork
+ {
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// A local DigiMesh device to get the network from.
+ /// If == null.
+ ///
+ ///
+ internal DigiMeshNetwork(DigiMeshDevice device)
+ : base(device) { }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/DigiPointDevice.cs b/XBeeLibrary.Core/DigiPointDevice.cs
new file mode 100644
index 0000000..df9e280
--- /dev/null
+++ b/XBeeLibrary.Core/DigiPointDevice.cs
@@ -0,0 +1,380 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Connection;
+using XBeeLibrary.Core.Events;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// This class represents a local Poit-to-multipoint device.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public class DigiPointDevice : XBeeDevice
+ {
+ ///
+ /// Class constructor. Instantiates a new object with the given
+ /// connection interface.
+ ///
+ /// The connection interface with the physical point-to-multipoint
+ /// device.
+ /// If == null.
+ ///
+ ///
+ ///
+ public DigiPointDevice(IConnectionInterface connectionInterface)
+ : base(connectionInterface) { }
+
+ // Events.
+ ///
+ /// Represents the method that will handle the explicit data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler ExplicitDataReceived
+ {
+ add
+ {
+ base.ExplicitDataReceived += value;
+ }
+ remove
+ {
+ base.ExplicitDataReceived -= value;
+ }
+ }
+
+ // Properties.
+ ///
+ /// The API output mode of the XBee device.
+ ///
+ /// The API output mode determines the format that the received data is output through the
+ /// serial interface of the XBee device.
+ ///
+ /// If the returned value of the API Output Mode command
+ /// is null or empty.
+ ///
+ public new APIOutputMode APIOutputMode
+ {
+ get
+ {
+ return base.APIOutputMode;
+ }
+ set
+ {
+ base.APIOutputMode = value;
+ }
+ }
+
+ ///
+ /// The protocol of the XBee device.
+ ///
+ ///
+ public override XBeeProtocol XBeeProtocol => XBeeProtocol.DIGI_POINT;
+
+ ///
+ /// Opens the connection interface associated with this XBee device.
+ ///
+ /// When opening the device an information reading process is automatically performed.
+ /// This includes:
+ ///
+ /// - 64-bit address.
+ /// - Node Identifier.
+ /// - Hardware version
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - 16-bit address (not for DigiMesh modules).
+ ///
+ /// If this device connection is already open.
+ /// If the operating mode of the device is
+ /// or
+ /// If the BLE authentication process fails.
+ /// If the timeout to read settings when initializing the
+ /// device elapses without response.
+ /// If there is any problem opening this device connection.
+ ///
+ ///
+ public override void Open()
+ {
+ base.Open();
+
+ if (IsRemote)
+ return;
+
+ if (base.XBeeProtocol != XBeeProtocol.DIGI_POINT)
+ throw new XBeeDeviceException("XBee device is not a " + XBeeProtocol.DIGI_POINT.GetDescription()
+ + " device, it is a " + base.XBeeProtocol.GetDescription() + " device.");
+ }
+
+ ///
+ /// Returns the network associated with this XBee device.
+ ///
+ /// The XBee network of the device.
+ /// If this device connection is not open.
+ ///
+ ///
+ public override XBeeNetwork GetNetwork()
+ {
+ if (network == null)
+ network = new DigiPointNetwork(this);
+ return network;
+ }
+
+ ///
+ /// Reads new explicit data received by this XBee device during the configured receive timeout.
+ ///
+ /// This method blocks until new explicit data is received or the configured receive timeout
+ /// expires.
+ ///
+ /// For non-blocking operations, register an event handler to .
+ ///
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this did not receive new explicit data during the configured receive timeout.
+ /// If the interface is not open.
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitData()
+ {
+ return base.ReadExplicitData();
+ }
+
+ ///
+ /// Reads new explicit data received by this XBee device during the configured receive timeout.
+ ///
+ /// This method blocks until new explicit data is received or the configured receive timeout
+ /// expires.
+ ///
+ /// For non-blocking operations, register an event handler to .
+ ///
+ /// The time to wait for new explicit data in milliseconds.
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this did not receive new explicit data during the configured receive timeout.
+ /// If 0.
+ /// If the interface is not open.
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitData(int timeout)
+ {
+ return base.ReadExplicitData(timeout);
+ }
+
+ ///
+ /// Reads new explicit data received from the given remote XBee device during the configured
+ /// receive timeout.
+ ///
+ /// This method blocks until new explicit data from the provided remote XBee device is
+ /// received or the configured receive timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to
+ /// .
+ /// The remote device to read explicit data from.
+ /// An object containing the explicit data, the source
+ /// address of the remote node that sent the data and other values related to the transmission.
+ /// null if this device did not receive new explicit data from the provided remote XBee
+ /// device during the configured receive timeout.
+ /// If == null.
+ /// If the interface is not open.
+ ///
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice)
+ {
+ return base.ReadExplicitDataFrom(remoteXBeeDevice);
+ }
+
+ ///
+ /// Reads new explicit data received from the given remote XBee device during the provided timeout.
+ ///
+ /// This method blocks until new explicit data from the provided remote XBee device is
+ /// received or the given timeout expires.
+ ///
+ /// For non-blocking operations, register an event handler to .
+ ///
+ /// The remote device to read explicit data from.
+ /// The time to wait for new explicit data in milliseconds.
+ /// An object containing the explicit data, the source address
+ /// of the remote node that sent the data and other values related to the transmission.
+ /// null if this device did not receive new data from the provided remote XBee device during
+ /// milliseconds.
+ /// If 0.
+ /// If == null.
+ /// If the interface is not open.
+ ///
+ ///
+ ///
+ public new ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ return base.ReadExplicitDataFrom(remoteXBeeDevice, timeout);
+ }
+
+ ///
+ /// Sends asynchronously the provided data in application layer mode to the XBee device of the
+ /// network corresponding to the given 64-bit address. Application layer mode means that you
+ /// need to specify the application layer fields to be sent with the data.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for
+ /// transmit status packet.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ ///
+ ///
+ public new void SendExplicitDataAsync(XBee64BitAddress address, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitDataAsync(address, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends asynchronously the provided data in application layer mode to the provided XBee device
+ /// choosing the optimal send method depending on the protocol of the local XBee device. Application
+ /// layer mode means that you need to specify the application layer fields to be sent with the data.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for transmit
+ /// status packet.
+ /// The XBee device of the network that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ ///
+ ///
+ public new void SendExplicitDataAsync(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitDataAsync(remoteXBeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data in application layer mode to the XBee device of the network corresponding
+ /// to the given 64-bit address. Application layer mode means that you need to specify the application
+ /// layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ /// The 64-bit address of the XBee that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If the sender device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public new void SendExplicitData(XBee64BitAddress address, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitData(address, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data in application layer mode to the provided XBee device choosing the
+ /// optimal send method depending on the protocol of the local XBee device. Application layer mode
+ /// means that you need to specify the application layer fields to be sent with the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ /// The XBee device of the network that will receive the data.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null
+ /// or if == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ public new void SendExplicitData(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ {
+ base.SendExplicitData(remoteXBeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+
+ ///
+ /// Sends the provided data to all the XBee nodes of the network (broadcast) in application layer mode.
+ /// Application layer mode means that you need to specify the application layer fields to be sent with
+ /// the data.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ /// Source endpoint for the transmission.
+ /// Destination endpoint for the transmission.
+ /// Cluster ID used in the transmission.
+ /// Profile ID used in the transmission.
+ /// Byte array containing the data to be sent.
+ /// If == null.
+ /// If clusterID.Length != 2
+ /// or if profileID.Length != 2.
+ /// If the interface is not open.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the packet is not
+ /// an instance of
+ /// or if it is not an instance of
+ /// or if when it is correct, its status is different from .
+ /// If there is any other XBee related error.
+ ///
+ public new void SendBroadcastExplicitData(byte sourceEndpoint, byte destEndpoint, byte[] clusterID, byte[] profileID,
+ byte[] data)
+ {
+ base.SendBroadcastExplicitData(sourceEndpoint, destEndpoint, clusterID, profileID, data);
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/DigiPointNetwork.cs b/XBeeLibrary.Core/DigiPointNetwork.cs
new file mode 100644
index 0000000..2cc341b
--- /dev/null
+++ b/XBeeLibrary.Core/DigiPointNetwork.cs
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// This class represents a DigiPoint Network.
+ ///
+ /// The network allows the discovery of remote devices in the same network as the local
+ /// one and stores them.
+ ///
+ ///
+ ///
+ ///
+ public class DigiPointNetwork : XBeeNetwork
+ {
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// A local DigiPoint device to get the network from.
+ /// If == null.
+ ///
+ ///
+ internal DigiPointNetwork(DigiPointDevice device)
+ : base(device) { }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Events/DataReceivedEventArgs.cs b/XBeeLibrary.Core/Events/DataReceivedEventArgs.cs
new file mode 100644
index 0000000..3ad4903
--- /dev/null
+++ b/XBeeLibrary.Core/Events/DataReceivedEventArgs.cs
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the XBee message for the data received event.
+ ///
+ public class DataReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The XBee message.
+ public DataReceivedEventArgs(XBeeMessage xbeeMessage)
+ {
+ DataReceived = xbeeMessage;
+ }
+
+ // Properties.
+ ///
+ /// The object containing the data, the
+ /// that sent the data and a flag indicating whether the data was sent via broadcast or not.
+ ///
+ ///
+ ///
+ public XBeeMessage DataReceived { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/DeviceDiscoveredEventArgs.cs b/XBeeLibrary.Core/Events/DeviceDiscoveredEventArgs.cs
new file mode 100644
index 0000000..ac1ec37
--- /dev/null
+++ b/XBeeLibrary.Core/Events/DeviceDiscoveredEventArgs.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the discovered XBee device for the device discovered event.
+ ///
+ public class DeviceDiscoveredEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The discovered remote device.
+ public DeviceDiscoveredEventArgs(RemoteXBeeDevice discoveredDevice)
+ {
+ DiscoveredDevice = discoveredDevice;
+ }
+
+ // Properties.
+ ///
+ /// The discovered object.
+ ///
+ ///
+ public RemoteXBeeDevice DiscoveredDevice { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/DiscoveryErrorEventArgs.cs b/XBeeLibrary.Core/Events/DiscoveryErrorEventArgs.cs
new file mode 100644
index 0000000..ef55ef3
--- /dev/null
+++ b/XBeeLibrary.Core/Events/DiscoveryErrorEventArgs.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the error from the received discovery error event.
+ ///
+ public class DiscoveryErrorEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The error message.
+ public DiscoveryErrorEventArgs(string error)
+ {
+ Error = error;
+ }
+
+ // Properties.
+ ///
+ /// The error string.
+ ///
+ public string Error { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/DiscoveryFinishedEventArgs.cs b/XBeeLibrary.Core/Events/DiscoveryFinishedEventArgs.cs
new file mode 100644
index 0000000..718e83a
--- /dev/null
+++ b/XBeeLibrary.Core/Events/DiscoveryFinishedEventArgs.cs
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the notification for the received discovery finished event.
+ ///
+ public class DiscoveryFinishedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The error message, if any.
+ public DiscoveryFinishedEventArgs(string error)
+ {
+ Error = error;
+ }
+
+ // Properties.
+ ///
+ /// The error string, if any.
+ ///
+ public string Error { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/ExplicitDataReceivedEventArgs.cs b/XBeeLibrary.Core/Events/ExplicitDataReceivedEventArgs.cs
new file mode 100644
index 0000000..47095ce
--- /dev/null
+++ b/XBeeLibrary.Core/Events/ExplicitDataReceivedEventArgs.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the explicit XBee message for the explicit data received event.
+ ///
+ public class ExplicitDataReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The received Explicit XBee message.
+ public ExplicitDataReceivedEventArgs(ExplicitXBeeMessage explicitXBeeMessage)
+ {
+ ExplicitDataReceived = explicitXBeeMessage;
+ }
+
+ // Properties.
+ ///
+ /// The object containing the data, the
+ /// that sent the data, a flag indicating whether the data was
+ /// sent via broadcast or not and the application layer fields (source endpoint, destination
+ /// endpoint, cluster ID and profile ID).
+ ///
+ ///
+ public ExplicitXBeeMessage ExplicitDataReceived { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/IOSampleReceivedEventArgs.cs b/XBeeLibrary.Core/Events/IOSampleReceivedEventArgs.cs
new file mode 100644
index 0000000..3a2a2f8
--- /dev/null
+++ b/XBeeLibrary.Core/Events/IOSampleReceivedEventArgs.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.IO;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides data for IO sample received event.
+ ///
+ public class IOSampleReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The remote XBee device.
+ /// The IO sample.
+ public IOSampleReceivedEventArgs(RemoteXBeeDevice remoteDevice, IOSample ioSample)
+ {
+ RemoteDevice = remoteDevice;
+ IOSample = ioSample;
+ }
+
+ // Properties.
+ ///
+ /// The remote XBee device that sent the sample.
+ ///
+ ///
+ public RemoteXBeeDevice RemoteDevice { get; private set; }
+
+ ///
+ /// The received IO sample.
+ ///
+ ///
+ public IOSample IOSample { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/IPDataReceivedEventArgs.cs b/XBeeLibrary.Core/Events/IPDataReceivedEventArgs.cs
new file mode 100644
index 0000000..a132870
--- /dev/null
+++ b/XBeeLibrary.Core/Events/IPDataReceivedEventArgs.cs
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the IP Data received event.
+ ///
+ public class IPDataReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The received IP Data message.
+ public IPDataReceivedEventArgs(IPMessage ipMessage)
+ {
+ IPDataReceived = ipMessage;
+ }
+
+ // Properties.
+ ///
+ /// The received IP Data message that contains the data, the IP address that sent the data,
+ /// the source and destination ports and the of the transmission.
+ ///
+ ///
+ public IPMessage IPDataReceived { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/ModemStatusReceivedEventArgs.cs b/XBeeLibrary.Core/Events/ModemStatusReceivedEventArgs.cs
new file mode 100644
index 0000000..e16c0ac
--- /dev/null
+++ b/XBeeLibrary.Core/Events/ModemStatusReceivedEventArgs.cs
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the modem status received event.
+ ///
+ public class ModemStatusReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The modem status received.
+ public ModemStatusReceivedEventArgs(ModemStatusEvent modemStatusEvent)
+ {
+ ModemStatusEvent = modemStatusEvent;
+ }
+
+ // Properties.
+ ///
+ /// The Modem Status received.
+ ///
+ ///
+ public ModemStatusEvent ModemStatusEvent { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/PacketReceivedEventArgs.cs b/XBeeLibrary.Core/Events/PacketReceivedEventArgs.cs
new file mode 100644
index 0000000..a5fc612
--- /dev/null
+++ b/XBeeLibrary.Core/Events/PacketReceivedEventArgs.cs
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Packet;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the XBee packet received event.
+ ///
+ public class PacketReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The received packet.
+ public PacketReceivedEventArgs(XBeePacket packet)
+ {
+ ReceivedPacket = packet;
+ }
+
+ // Properties.
+ ///
+ /// The received object.
+ ///
+ ///
+ public XBeePacket ReceivedPacket { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/Relay/BluetoothDataReceivedEventArgs.cs b/XBeeLibrary.Core/Events/Relay/BluetoothDataReceivedEventArgs.cs
new file mode 100644
index 0000000..59c37a4
--- /dev/null
+++ b/XBeeLibrary.Core/Events/Relay/BluetoothDataReceivedEventArgs.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Events.Relay
+{
+ ///
+ /// Provides the contents of the Bluetooth data received event.
+ ///
+ public class BluetoothDataReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided
+ /// parameters.
+ ///
+ /// The received data.
+ public BluetoothDataReceivedEventArgs(byte[] data)
+ {
+ Data = data;
+ }
+
+ // Properties.
+ ///
+ /// The received data.
+ ///
+ public byte[] Data { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/Relay/MicroPythonDataReceivedEventArgs.cs b/XBeeLibrary.Core/Events/Relay/MicroPythonDataReceivedEventArgs.cs
new file mode 100644
index 0000000..1c9c88d
--- /dev/null
+++ b/XBeeLibrary.Core/Events/Relay/MicroPythonDataReceivedEventArgs.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Events.Relay
+{
+ ///
+ /// Provides the contents of the MicroPython data received event.
+ ///
+ public class MicroPythonDataReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided
+ /// parameters.
+ ///
+ /// The received data.
+ public MicroPythonDataReceivedEventArgs(byte[] data)
+ {
+ Data = data;
+ }
+
+ // Properties.
+ ///
+ /// The received data.
+ ///
+ public byte[] Data { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/Relay/SerialDataReceivedEventArgs.cs b/XBeeLibrary.Core/Events/Relay/SerialDataReceivedEventArgs.cs
new file mode 100644
index 0000000..2f290df
--- /dev/null
+++ b/XBeeLibrary.Core/Events/Relay/SerialDataReceivedEventArgs.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Events.Relay
+{
+ ///
+ /// Provides the contents of the serial data received event.
+ ///
+ public class SerialDataReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided
+ /// parameters.
+ ///
+ /// The received data.
+ public SerialDataReceivedEventArgs(byte[] data)
+ {
+ Data = data;
+ }
+
+ // Properties.
+ ///
+ /// The received data.
+ ///
+ public byte[] Data { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/SMSReceivedEventArgs.cs b/XBeeLibrary.Core/Events/SMSReceivedEventArgs.cs
new file mode 100644
index 0000000..78aa692
--- /dev/null
+++ b/XBeeLibrary.Core/Events/SMSReceivedEventArgs.cs
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the SMS received event.
+ ///
+ public class SMSReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided parameters.
+ ///
+ /// The received SMS message.
+ public SMSReceivedEventArgs(SMSMessage smsMessage)
+ {
+ SMSReceived = smsMessage;
+ }
+
+ // Properties.
+ ///
+ /// The received SMS that contains the SMS text and the phone number that sent the message.
+ ///
+ ///
+ public SMSMessage SMSReceived { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Events/UserDataRelayReceivedEventArgs.cs b/XBeeLibrary.Core/Events/UserDataRelayReceivedEventArgs.cs
new file mode 100644
index 0000000..0608e40
--- /dev/null
+++ b/XBeeLibrary.Core/Events/UserDataRelayReceivedEventArgs.cs
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Events
+{
+ ///
+ /// Provides the contents of the User Data Relay received event.
+ ///
+ public class UserDataRelayReceivedEventArgs : EventArgs
+ {
+ ///
+ /// Instantiates a object with the provided
+ /// parameters.
+ ///
+ /// The User Data Relay message received.
+ ///
+ public UserDataRelayReceivedEventArgs(UserDataRelayMessage userDataRelayMessage)
+ {
+ UserDataRelayMessage = userDataRelayMessage;
+ }
+
+ // Properties.
+ ///
+ /// The User Data Relay message received.
+ ///
+ ///
+ public UserDataRelayMessage UserDataRelayMessage { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/ATCommandEmptyException.cs b/XBeeLibrary.Core/Exceptions/ATCommandEmptyException.cs
new file mode 100644
index 0000000..0e5cb7c
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/ATCommandEmptyException.cs
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when the answer received from an AT command is empty and
+ /// it shouldn't.
+ ///
+ public class ATCommandEmptyException : CommunicationException
+ {
+ // Constants.
+ const string DEFAULT_MESSAGE = "Response received for command '{0}' was empty.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The AT command that originated the exception.
+ public ATCommandEmptyException(string atCommand) : base(string.Format(DEFAULT_MESSAGE, atCommand))
+ {
+ ATCommand = atCommand;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// The error message that explains the reason for this exception.
+ /// The AT command that originated the exception.
+ public ATCommandEmptyException(string message, string atCommand) : base(message)
+ {
+ ATCommand = atCommand;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and the exception that is the cause of this exception.
+ ///
+ /// The error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a
+ /// null reference if no inner exception is specified.
+ /// The AT command that originated the exception.
+ public ATCommandEmptyException(string message, Exception innerException, string atCommand) : base(message, innerException)
+ {
+ ATCommand = atCommand;
+ }
+
+ // Properties.
+ ///
+ /// The AT command of the exception.
+ ///
+ public string ATCommand { get; private set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/ATCommandException.cs b/XBeeLibrary.Core/Exceptions/ATCommandException.cs
new file mode 100644
index 0000000..e935479
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/ATCommandException.cs
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when any problem related to the communication with the XBee
+ /// device occurs.
+ ///
+ public class ATCommandException : CommunicationException
+ {
+ // Constants.
+ const string DEFAULT_MESSAGE = "There was a problem sending the AT command packet.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ATCommandException(ATCommandStatus atCommandStatus) : base(DEFAULT_MESSAGE)
+ {
+ CommandStatus = atCommandStatus;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The status of the AT command response.
+ public ATCommandException(string message, ATCommandStatus atCommandStatus) : base(message)
+ {
+ CommandStatus = atCommandStatus;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified error
+ /// message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ /// The status of the AT command response.
+ public ATCommandException(string message, Exception innerException, ATCommandStatus atCommandStatus) : base(message, innerException)
+ {
+ CommandStatus = atCommandStatus;
+ }
+
+ // Properties.
+ ///
+ /// The of the exception containing information about the AT
+ /// command response.
+ ///
+ public ATCommandStatus CommandStatus { get; private set; }
+
+ ///
+ /// The text containing the status of the AT command response.
+ ///
+ public string CommandStatusMessage { get { return CommandStatus.GetDescription(); } }
+
+ ///
+ /// The message reported by this exception.
+ ///
+ public override string Message
+ {
+ get
+ {
+ return string.Format("{0} > {1}", base.Message, CommandStatusMessage);
+ }
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/BluetoothAuthenticationException.cs b/XBeeLibrary.Core/Exceptions/BluetoothAuthenticationException.cs
new file mode 100644
index 0000000..b369472
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/BluetoothAuthenticationException.cs
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when trying authenticate over bluetooth with an XBee device and
+ /// there is an error.
+ ///
+ public class BluetoothAuthenticationException : Exception
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The bluetooth authentication process failed.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BluetoothAuthenticationException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// The error message that explains the reason for this exception.
+ public BluetoothAuthenticationException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with
+ /// a specified error message and the exception that is the cause of this exception.
+ ///
+ /// The error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public BluetoothAuthenticationException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/CommunicationException.cs b/XBeeLibrary.Core/Exceptions/CommunicationException.cs
new file mode 100644
index 0000000..16d24c9
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/CommunicationException.cs
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when any problem related to the communication with the XBee
+ /// device occurs.
+ ///
+ public class CommunicationException : XBeeException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public CommunicationException() : base() { }
+
+ ///
+ /// Initializes a new instance of the class with the
+ /// exception that is the cause of this exception.
+ ///
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public CommunicationException(Exception innerException) : base(null, innerException) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public CommunicationException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public CommunicationException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/ConnectionException.cs b/XBeeLibrary.Core/Exceptions/ConnectionException.cs
new file mode 100644
index 0000000..e5aaa34
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/ConnectionException.cs
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when any problem related to the connection with the XBee
+ /// device occurs.
+ ///
+ public class ConnectionException : XBeeException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ConnectionException() : base() { }
+
+ ///
+ /// Initializes a new instance of the class with the exception
+ /// that is the cause of this exception.
+ ///
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public ConnectionException(Exception innerException) : base(null, innerException) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public ConnectionException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public ConnectionException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/InterfaceAlreadyOpenException.cs b/XBeeLibrary.Core/Exceptions/InterfaceAlreadyOpenException.cs
new file mode 100644
index 0000000..74b38bf
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/InterfaceAlreadyOpenException.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when trying to open an interface with an invalid configuration.
+ /// Usually happens when the XBee device is communicating through a serial port.
+ ///
+ public class InterfaceAlreadyOpenException : Exception
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The connection interface is already open.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InterfaceAlreadyOpenException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public InterfaceAlreadyOpenException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public InterfaceAlreadyOpenException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/InterfaceInUseException.cs b/XBeeLibrary.Core/Exceptions/InterfaceInUseException.cs
new file mode 100644
index 0000000..24997ef
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/InterfaceInUseException.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when trying to open the port/communication interface but it
+ /// is already in use by other applications.
+ ///
+ public class InterfaceInUseException : ConnectionException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The connection interface is already in use by other application(s).";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InterfaceInUseException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public InterfaceInUseException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public InterfaceInUseException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/InterfaceNotOpenException.cs b/XBeeLibrary.Core/Exceptions/InterfaceNotOpenException.cs
new file mode 100644
index 0000000..7f8431c
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/InterfaceNotOpenException.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when trying to open an interface with an invalid configuration.
+ /// Usually happens when the XBee device is communicating through a serial port.
+ ///
+ public class InterfaceNotOpenException : Exception
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The connection interface is not open.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InterfaceNotOpenException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public InterfaceNotOpenException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public InterfaceNotOpenException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/InvalidConfigurationException.cs b/XBeeLibrary.Core/Exceptions/InvalidConfigurationException.cs
new file mode 100644
index 0000000..be0dc14
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/InvalidConfigurationException.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when trying to open an interface with an invalid configuration.
+ /// Usually happens when the XBee device is communicating through a serial port.
+ ///
+ public class InvalidConfigurationException : ConnectionException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The configuration used to open the interface is invalid.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InvalidConfigurationException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public InvalidConfigurationException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public InvalidConfigurationException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/InvalidInterfaceException.cs b/XBeeLibrary.Core/Exceptions/InvalidInterfaceException.cs
new file mode 100644
index 0000000..b8d0163
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/InvalidInterfaceException.cs
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when trying to open a non-existing interface.
+ ///
+ public class InvalidInterfaceException : ConnectionException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The connection interface you are trying to access is invalid or does not exist.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InvalidInterfaceException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public InvalidInterfaceException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public InvalidInterfaceException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/InvalidOperatingModeException.cs b/XBeeLibrary.Core/Exceptions/InvalidOperatingModeException.cs
new file mode 100644
index 0000000..5e36bb4
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/InvalidOperatingModeException.cs
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when performing any action with the XBee device and its operating
+ /// mode is different than and .
+ ///
+ public class InvalidOperatingModeException : CommunicationException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The operating mode of the XBee device is not supported by the library.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InvalidOperatingModeException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with the
+ /// specified operating .
+ ///
+ /// The unsupported operating mode.
+ public InvalidOperatingModeException(OperatingMode mode) : base("Unsupported operating mode: " + mode) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// The error message that explains the reason for this exception.
+ public InvalidOperatingModeException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public InvalidOperatingModeException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/InvalidPacketException.cs b/XBeeLibrary.Core/Exceptions/InvalidPacketException.cs
new file mode 100644
index 0000000..f03fc30
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/InvalidPacketException.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when there is an error parsing an API packet from the
+ /// input stream.
+ ///
+ public class InvalidPacketException : CommunicationException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The XBee API packet is not properly formed.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public InvalidPacketException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public InvalidPacketException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null reference
+ /// if no inner exception is specified.
+ public InvalidPacketException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/OperationNotSupportedException.cs b/XBeeLibrary.Core/Exceptions/OperationNotSupportedException.cs
new file mode 100644
index 0000000..7d3e1c9
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/OperationNotSupportedException.cs
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when the operation performed is not supported by the XBee device.
+ ///
+ public class OperationNotSupportedException : XBeeDeviceException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "The requested operation is not supported by either the connection interface or the XBee device.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public OperationNotSupportedException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public OperationNotSupportedException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public OperationNotSupportedException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/ParsingException.cs b/XBeeLibrary.Core/Exceptions/ParsingException.cs
new file mode 100644
index 0000000..eb254eb
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/ParsingException.cs
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception is thrown when there is an error parsing an MXI or XML firmware definition file.
+ ///
+ public class ParsingException : Exception
+ {
+ ///
+ /// Creates a ParsingException with the specified message.
+ ///
+ /// The associated message.
+ public ParsingException(string message) : base(message) { }
+
+ ///
+ /// Creates a ParsingException with the specified message and exception.
+ ///
+ /// Exception that caused this one.
+ /// The associated message.
+ public ParsingException(Exception exception, string message) : base(message, exception) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/PermissionDeniedException.cs b/XBeeLibrary.Core/Exceptions/PermissionDeniedException.cs
new file mode 100644
index 0000000..d133992
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/PermissionDeniedException.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when the user does not have the appropriate access to the
+ /// connection interface. Usually happens when the XBee device is communicating through a serial port.
+ ///
+ public class PermissionDeniedException : ConnectionException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "You don't have the required permissions to access the connection interface.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public PermissionDeniedException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public PermissionDeniedException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a
+ /// specified error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public PermissionDeniedException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/TimeoutException.cs b/XBeeLibrary.Core/Exceptions/TimeoutException.cs
new file mode 100644
index 0000000..da63e35
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/TimeoutException.cs
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when performing synchronous operations and the configured time
+ /// expires.
+ ///
+ public class TimeoutException : CommunicationException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "There was a timeout while executing the requested operation.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public TimeoutException() : base(DEFAULT_MESSAGE) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public TimeoutException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified error
+ /// message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a
+ /// null reference if no inner exception is specified.
+ public TimeoutException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/TransmitException.cs b/XBeeLibrary.Core/Exceptions/TransmitException.cs
new file mode 100644
index 0000000..008cf45
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/TransmitException.cs
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using XBeeLibrary.Core.Models;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when receiving a transmit status different than
+ /// after sending an XBee API packet.
+ ///
+ public class TransmitException : CommunicationException
+ {
+ // Constants.
+ private const string DEFAULT_MESSAGE = "There was a problem transmitting the XBee API packet.";
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The status of the transmission.
+ public TransmitException(XBeeTransmitStatus transmitStatus) : base(DEFAULT_MESSAGE)
+ {
+ TransmitStatus = transmitStatus;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The status of the transmission.
+ public TransmitException(string message, XBeeTransmitStatus transmitStatus) : base(message)
+ {
+ TransmitStatus = transmitStatus;
+ }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a
+ /// null reference if no inner exception is specified.
+ /// The status of the transmission.
+ public TransmitException(string message, Exception innerException, XBeeTransmitStatus transmitStatus) : base(message, innerException)
+ {
+ TransmitStatus = transmitStatus;
+ }
+
+ // Properties.
+ ///
+ /// The of the exception containing information about
+ /// the transmission.
+ ///
+ ///
+ public XBeeTransmitStatus TransmitStatus { get; private set; }
+
+ ///
+ /// The transmit status message.
+ ///
+ public string TransmitStatusMessage { get { return TransmitStatus.GetDescription(); } }
+
+ ///
+ /// The exception message.
+ ///
+ public override string Message
+ {
+ get
+ {
+ return string.Format("{0} > {1}", base.Message, TransmitStatus.GetDescription());
+ }
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/XBeeDeviceException.cs b/XBeeLibrary.Core/Exceptions/XBeeDeviceException.cs
new file mode 100644
index 0000000..7aac0ea
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/XBeeDeviceException.cs
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// This exception will be thrown when any problem related to the XBee device occurs.
+ ///
+ public class XBeeDeviceException : XBeeException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public XBeeDeviceException() : base() { }
+
+ ///
+ /// Initializes a new instance of the class with the exception
+ /// that is the cause of this exception.
+ ///
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public XBeeDeviceException(Exception innerException) : base(null, innerException) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public XBeeDeviceException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified
+ /// error message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public XBeeDeviceException(string message, Exception innerException) : base(message, innerException) { }
+
+ }
+}
diff --git a/XBeeLibrary.Core/Exceptions/XBeeException.cs b/XBeeLibrary.Core/Exceptions/XBeeException.cs
new file mode 100644
index 0000000..9dc5762
--- /dev/null
+++ b/XBeeLibrary.Core/Exceptions/XBeeException.cs
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Exceptions
+{
+ ///
+ /// Generic XBee API exception. This class and its subclasses indicate conditions that an application
+ /// might want to catch. This exception can be thrown when any problem related to the XBee device occurs.
+ ///
+ public class XBeeException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public XBeeException() : base() { }
+
+ ///
+ /// Initializes a new instance of the class with the exception that
+ /// is the cause of this exception.
+ ///
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public XBeeException(Exception innerException) : base(null, innerException) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified error
+ /// message.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ public XBeeException(string message) : base(message) { }
+
+ ///
+ /// Initializes a new instance of the class with a specified error
+ /// message and the exception that is the cause of this exception.
+ ///
+ /// ThThe error message that explains the reason for this exception.
+ /// The exception that is the cause of the current exception, or a null
+ /// reference if no inner exception is specified.
+ public XBeeException(string message, Exception innerException) : base(message, innerException) { }
+ }
+}
diff --git a/XBeeLibrary/IO/IOLine.cs b/XBeeLibrary.Core/IO/IOLine.cs
similarity index 68%
rename from XBeeLibrary/IO/IOLine.cs
rename to XBeeLibrary.Core/IO/IOLine.cs
index a50171d..d5d8cd1 100644
--- a/XBeeLibrary/IO/IOLine.cs
+++ b/XBeeLibrary.Core/IO/IOLine.cs
@@ -1,154 +1,179 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Kveer.XBeeApi.IO
-{
- ///
- /// Enumerates the different IO lines that can be found in the XBee devices.
- /// Depending on the hardware and firmware of the device, the number of lines that can be used as well as their functionality may vary. Refer to the product manual to learn more about the IO lines of your XBee device.
- ///
- public enum IOLine
- {
- UNKNOWN = 0xff,
- DIO0_AD0 = 0,
- DIO0_AD1 = 1,
- DIO0_AD2 = 2,
- DIO0_AD3 = 3,
- DIO0_AD4 = 4,
- DIO0_AD5 = 5,
- DIO6 = 6,
- DIO7 = 7,
- DIO8 = 8,
- DIO9 = 9,
- DIO10_PWM0 = 10,
- DIO11_PWM1 = 11,
- DIO12 = 12,
- DIO13 = 13,
- DIO14 = 14,
- DIO15 = 15,
- DIO16 = 16,
- DIO17 = 17,
- DIO18 = 18,
- DIO19 = 19
- }
-
- public static class IOLineExtensions
- {
- private static IDictionary lookup = new Dictionary();
-
- static IOLineExtensions()
- {
- lookup.Add(IOLine.DIO0_AD0, new IOLineStruct("DIO0/AD0", 0, "D0", null));
- lookup.Add(IOLine.DIO0_AD1, new IOLineStruct("DIO1/AD1", 1, "D1", null));
- lookup.Add(IOLine.DIO0_AD2, new IOLineStruct("DIO2/AD2", 2, "D2", null));
- lookup.Add(IOLine.DIO0_AD3, new IOLineStruct("DIO3/AD3", 3, "D3", null));
- lookup.Add(IOLine.DIO0_AD4, new IOLineStruct("DIO4/AD4", 4, "D4", null));
- lookup.Add(IOLine.DIO0_AD5, new IOLineStruct("DIO5/AD5", 5, "D5", null));
- lookup.Add(IOLine.DIO6, new IOLineStruct("DIO6", 6, "D6", null));
- lookup.Add(IOLine.DIO7, new IOLineStruct("DIO7", 7, "D7", null));
- lookup.Add(IOLine.DIO8, new IOLineStruct("DIO8", 8, "D8", null));
- lookup.Add(IOLine.DIO9, new IOLineStruct("DIO9", 9, "D9", null));
- lookup.Add(IOLine.DIO10_PWM0, new IOLineStruct("DIO10/PWM0", 10, "P0", "M0"));
- lookup.Add(IOLine.DIO11_PWM1, new IOLineStruct("DIO11/PWM1", 11, "P1", "M1"));
- lookup.Add(IOLine.DIO12, new IOLineStruct("DIO12", 12, "P2", null));
- lookup.Add(IOLine.DIO13, new IOLineStruct("DIO13", 13, "P3", null));
- lookup.Add(IOLine.DIO14, new IOLineStruct("DIO14", 14, "P4", null));
- lookup.Add(IOLine.DIO15, new IOLineStruct("DIO15", 15, "P5", null));
- lookup.Add(IOLine.DIO16, new IOLineStruct("DIO16", 16, "P6", null));
- lookup.Add(IOLine.DIO17, new IOLineStruct("DIO17", 17, "P7", null));
- lookup.Add(IOLine.DIO18, new IOLineStruct("DIO18", 18, "P8", null));
- lookup.Add(IOLine.DIO19, new IOLineStruct("DIO19", 19, "P9", null));
- }
-
- ///
- /// Gets the name of the IO line.
- ///
- public static string GetName(this IOLine source)
- {
- return lookup[source].Name;
- }
-
- ///
- /// Gets the configuration AT command associated to the IO line.
- ///
- public static string GetConfigurationATCommand(this IOLine source)
- {
- return lookup[source].ATCommand;
- }
-
- ///
- /// Indicates whether the IO line has PWM capability.
- ///
- public static bool HasPWMCapability(this IOLine source)
- {
- return lookup[source].HasPWMCapability;
- }
-
- ///
- /// Gets the PWM AT command associated to the IO line.
- ///
- public static string GetPWMDutyCycleATCommand(this IOLine source)
- {
- return lookup[source].ATPWMCommand;
- }
-
- ///
- /// Gets the associated to the given index.
- ///
- /// A dumb value to access the method.
- /// The index corresponding to the to retrieve.
- ///
- public static IOLine GetDIO(this IOLine dumb, int index)
- {
- return lookup.Where(l => l.Value.Index == index).Select(l => l.Key).FirstOrDefault();
- }
- }
-
- struct IOLineStruct
- {
- public IOLineStruct(string name, int index, string atCommand, string atPwmCommand)
- : this()
- {
- Name = name;
- Index = index;
- ATCommand = atCommand;
- ATPWMCommand = atPwmCommand;
- }
-
- ///
- /// Gets the name of the IO line.
- ///
- public string Name { get; private set; }
-
- ///
- /// Gets the configuration AT command associated to the IO line.
- ///
- public string ATCommand { get; private set; }
-
- ///
- /// Gets the PWM AT command associated to the IO line.
- ///
- public string ATPWMCommand { get; private set; }
-
- ///
- /// Gets the index of the IO line.
- ///
- public int Index { get; private set; }
-
- ///
- /// Indicates whether the IO line has PWM capability.
- ///
- public bool HasPWMCapability
- {
- get { return ATPWMCommand != null; }
- }
-
- public override string ToString()
- {
- return Name;
- }
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XBeeLibrary.Core.IO
+{
+ ///
+ /// Enumerates the different IO lines that can be found in the XBee devices.
+ ///
+ /// Depending on the hardware and firmware of the device, the number of lines that can
+ /// be used as well as their functionality may vary. Refer to the product manual to learn more
+ /// about the IO lines of your XBee device.
+ public enum IOLine
+ {
+ UNKNOWN = 0xff,
+ DIO0_AD0 = 0,
+ DIO0_AD1 = 1,
+ DIO0_AD2 = 2,
+ DIO0_AD3 = 3,
+ DIO0_AD4 = 4,
+ DIO0_AD5 = 5,
+ DIO6 = 6,
+ DIO7 = 7,
+ DIO8 = 8,
+ DIO9 = 9,
+ DIO10_PWM0 = 10,
+ DIO11_PWM1 = 11,
+ DIO12 = 12,
+ DIO13 = 13,
+ DIO14 = 14,
+ DIO15 = 15,
+ DIO16 = 16,
+ DIO17 = 17,
+ DIO18 = 18,
+ DIO19 = 19
+ }
+
+ public static class IOLineExtensions
+ {
+ private static IDictionary lookup = new Dictionary();
+
+ static IOLineExtensions()
+ {
+ lookup.Add(IOLine.DIO0_AD0, new IOLineStruct("DIO0/AD0", 0, "D0", null));
+ lookup.Add(IOLine.DIO0_AD1, new IOLineStruct("DIO1/AD1", 1, "D1", null));
+ lookup.Add(IOLine.DIO0_AD2, new IOLineStruct("DIO2/AD2", 2, "D2", null));
+ lookup.Add(IOLine.DIO0_AD3, new IOLineStruct("DIO3/AD3", 3, "D3", null));
+ lookup.Add(IOLine.DIO0_AD4, new IOLineStruct("DIO4/AD4", 4, "D4", null));
+ lookup.Add(IOLine.DIO0_AD5, new IOLineStruct("DIO5/AD5", 5, "D5", null));
+ lookup.Add(IOLine.DIO6, new IOLineStruct("DIO6", 6, "D6", null));
+ lookup.Add(IOLine.DIO7, new IOLineStruct("DIO7", 7, "D7", null));
+ lookup.Add(IOLine.DIO8, new IOLineStruct("DIO8", 8, "D8", null));
+ lookup.Add(IOLine.DIO9, new IOLineStruct("DIO9", 9, "D9", null));
+ lookup.Add(IOLine.DIO10_PWM0, new IOLineStruct("DIO10/PWM0", 10, "P0", "M0"));
+ lookup.Add(IOLine.DIO11_PWM1, new IOLineStruct("DIO11/PWM1", 11, "P1", "M1"));
+ lookup.Add(IOLine.DIO12, new IOLineStruct("DIO12", 12, "P2", null));
+ lookup.Add(IOLine.DIO13, new IOLineStruct("DIO13", 13, "P3", null));
+ lookup.Add(IOLine.DIO14, new IOLineStruct("DIO14", 14, "P4", null));
+ lookup.Add(IOLine.DIO15, new IOLineStruct("DIO15", 15, "P5", null));
+ lookup.Add(IOLine.DIO16, new IOLineStruct("DIO16", 16, "P6", null));
+ lookup.Add(IOLine.DIO17, new IOLineStruct("DIO17", 17, "P7", null));
+ lookup.Add(IOLine.DIO18, new IOLineStruct("DIO18", 18, "P8", null));
+ lookup.Add(IOLine.DIO19, new IOLineStruct("DIO19", 19, "P9", null));
+ }
+
+ ///
+ /// Gets the name of the IO line.
+ ///
+ ///
+ /// The name of the IO line.
+ public static string GetName(this IOLine source)
+ {
+ return lookup[source].Name;
+ }
+
+ ///
+ /// Gets the configuration AT command associated to the IO line.
+ ///
+ ///
+ /// The configuration AT command associated to the IO line.
+ public static string GetConfigurationATCommand(this IOLine source)
+ {
+ return lookup[source].ATCommand;
+ }
+
+ ///
+ /// Indicates whether the IO line has PWM capability.
+ ///
+ ///
+ /// true if the IO line has PWM capability, false otherwise.
+ public static bool HasPWMCapability(this IOLine source)
+ {
+ return lookup[source].HasPWMCapability;
+ }
+
+ ///
+ /// Gets the PWM AT command associated to the IO line.
+ ///
+ ///
+ /// The PWM AT command associated to the IO line.
+ public static string GetPWMDutyCycleATCommand(this IOLine source)
+ {
+ return lookup[source].ATPWMCommand;
+ }
+
+ ///
+ /// Gets the associated to the given index.
+ ///
+ ///
+ /// The index corresponding to the to retrieve.
+ ///
+ public static IOLine GetDIO(this IOLine source, int index)
+ {
+ return lookup.Where(l => l.Value.Index == index).Select(l => l.Key).FirstOrDefault();
+ }
+ }
+
+ struct IOLineStruct
+ {
+ public IOLineStruct(string name, int index, string atCommand, string atPwmCommand)
+ : this()
+ {
+ Name = name;
+ Index = index;
+ ATCommand = atCommand;
+ ATPWMCommand = atPwmCommand;
+ }
+
+ // Properties.
+ ///
+ /// The name of the IO line.
+ ///
+ public string Name { get; private set; }
+
+ ///
+ /// The configuration AT command associated to the IO line.
+ ///
+ public string ATCommand { get; private set; }
+
+ ///
+ /// The PWM AT command associated to the IO line.
+ ///
+ public string ATPWMCommand { get; private set; }
+
+ ///
+ /// The index of the IO line.
+ ///
+ public int Index { get; private set; }
+
+ ///
+ /// Indicates whether the IO line has PWM capability.
+ ///
+ public bool HasPWMCapability
+ {
+ get { return ATPWMCommand != null; }
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+}
diff --git a/XBeeLibrary/IO/IOMode.cs b/XBeeLibrary.Core/IO/IOMode.cs
similarity index 70%
rename from XBeeLibrary/IO/IOMode.cs
rename to XBeeLibrary.Core/IO/IOMode.cs
index 7a2fbf0..72c2125 100644
--- a/XBeeLibrary/IO/IOMode.cs
+++ b/XBeeLibrary.Core/IO/IOMode.cs
@@ -1,102 +1,116 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Kveer.XBeeApi.IO
-{
- ///
- /// Enumerates the different Input/Output modes that an IO line can be configured with.
- ///
- ///
- public enum IOMode
- {
- UNKOWN = 0xff,
- DISABLED = 0,
- SPECIAL_FUNCTIONALITY = 1,
- PWM = 2,
- ADC = 20,
- DIGITAL_IN = 3,
- DIGITAL_OUT_LOW = 4,
- DIGITAL_OUT_HIGH = 5
- }
-
- public static class IOModeExtensions
- {
- private static IDictionary lookupTable = new Dictionary();
-
- static IOModeExtensions()
- {
- lookupTable.Add(IOMode.DISABLED, new IOModeStruct(0, "Disabled"));
- lookupTable.Add(IOMode.SPECIAL_FUNCTIONALITY, new IOModeStruct(1, "Firmware special functionality"));
- lookupTable.Add(IOMode.PWM, new IOModeStruct(2, "PWM output"));
- lookupTable.Add(IOMode.ADC, new IOModeStruct(2, "Analog to Digital Converter"));
- lookupTable.Add(IOMode.DIGITAL_IN, new IOModeStruct(3, "Digital input"));
- lookupTable.Add(IOMode.DIGITAL_OUT_LOW, new IOModeStruct(4, "Digital output, Low"));
- lookupTable.Add(IOMode.DIGITAL_OUT_HIGH, new IOModeStruct(5, "Digital output, High"));
- }
-
- ///
- /// Gets the IO mode ID.
- ///
- ///
- /// IO mode ID.
- public static int GetId(this IOMode source)
- {
- return lookupTable[source].Id;
- }
-
- ///
- /// Gets the IO mode name.
- ///
- ///
- /// IO mode name.
- public static string GetName(this IOMode source)
- {
- return lookupTable[source].Name;
- }
-
- ///
- /// Gets the corresponding to the provided mode Id.
- ///
- ///
- /// The ID of the to retrieve.
- /// The corresponding to the provided mode ID.
- public static IOMode GetIOMode(this IOMode dumb, int modeID)
- {
- return GetIOMode(dumb, modeID, IOLine.UNKNOWN);
- }
-
- ///
- /// Gets the corresponding to the provided mode Id and IO line.
- ///
- ///
- /// The ID of the to retrieve.
- /// The IO line to retrieve its
- /// The corresponding to the provided mode ID and IO line.
- public static IOMode GetIOMode(this IOMode dumb, int modeID, IOLine ioline)
- {
- if (modeID == lookupTable[IOMode.ADC].Id)
- {
- return ioline != IOLine.UNKNOWN && ioline.HasPWMCapability() ? IOMode.PWM : IOMode.ADC;
- }
-
- return lookupTable.Where(io => io.Value.Id == modeID).Select(io => io.Key).FirstOrDefault();
- }
- }
-
- struct IOModeStruct
- {
- public int Id { get; private set; }
-
- public string Name { get; private set; }
-
- public IOModeStruct(int id, string name)
- : this()
- {
- Id = id;
- Name = name;
- }
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XBeeLibrary.Core.IO
+{
+ ///
+ /// Enumerates the different Input/Output modes that an IO line can be configured with.
+ ///
+ ///
+ public enum IOMode
+ {
+ UNKOWN = 0xff,
+ DISABLED = 0,
+ SPECIAL_FUNCTIONALITY = 1,
+ PWM = 2,
+ ADC = 20,
+ DIGITAL_IN = 3,
+ DIGITAL_OUT_LOW = 4,
+ DIGITAL_OUT_HIGH = 5
+ }
+
+ public static class IOModeExtensions
+ {
+ private static IDictionary lookupTable = new Dictionary();
+
+ static IOModeExtensions()
+ {
+ lookupTable.Add(IOMode.DISABLED, new IOModeStruct(0, "Disabled"));
+ lookupTable.Add(IOMode.SPECIAL_FUNCTIONALITY, new IOModeStruct(1, "Firmware special functionality"));
+ lookupTable.Add(IOMode.PWM, new IOModeStruct(2, "PWM output"));
+ lookupTable.Add(IOMode.ADC, new IOModeStruct(2, "Analog to Digital Converter"));
+ lookupTable.Add(IOMode.DIGITAL_IN, new IOModeStruct(3, "Digital input"));
+ lookupTable.Add(IOMode.DIGITAL_OUT_LOW, new IOModeStruct(4, "Digital output, Low"));
+ lookupTable.Add(IOMode.DIGITAL_OUT_HIGH, new IOModeStruct(5, "Digital output, High"));
+ }
+
+ ///
+ /// Gets the IO mode ID.
+ ///
+ ///
+ /// IO mode ID.
+ public static int GetId(this IOMode source)
+ {
+ return lookupTable[source].Id;
+ }
+
+ ///
+ /// Gets the IO mode name.
+ ///
+ ///
+ /// IO mode name.
+ public static string GetName(this IOMode source)
+ {
+ return lookupTable[source].Name;
+ }
+
+ ///
+ /// Gets the corresponding to the provided mode Id.
+ ///
+ ///
+ /// The ID of the to retrieve.
+ /// The corresponding to the provided mode ID.
+ public static IOMode GetIOMode(this IOMode source, int modeID)
+ {
+ return GetIOMode(source, modeID, IOLine.UNKNOWN);
+ }
+
+ ///
+ /// Gets the corresponding to the provided mode Id and IO line.
+ ///
+ ///
+ /// The ID of the to retrieve.
+ /// The IO line to retrieve its
+ /// The corresponding to the provided mode ID and IO line.
+ public static IOMode GetIOMode(this IOMode source, int modeID, IOLine ioline)
+ {
+ if (modeID == lookupTable[IOMode.ADC].Id)
+ {
+ return ioline != IOLine.UNKNOWN && ioline.HasPWMCapability() ? IOMode.PWM : IOMode.ADC;
+ }
+
+ return lookupTable.Where(io => io.Value.Id == modeID).Select(io => io.Key).FirstOrDefault();
+ }
+ }
+
+ struct IOModeStruct
+ {
+ public int Id { get; private set; }
+
+ public string Name { get; private set; }
+
+ public IOModeStruct(int id, string name)
+ : this()
+ {
+ Id = id;
+ Name = name;
+ }
+ }
+}
diff --git a/XBeeLibrary/IO/IOSample.cs b/XBeeLibrary.Core/IO/IOSample.cs
similarity index 63%
rename from XBeeLibrary/IO/IOSample.cs
rename to XBeeLibrary.Core/IO/IOSample.cs
index 457e90c..d13ad34 100644
--- a/XBeeLibrary/IO/IOSample.cs
+++ b/XBeeLibrary.Core/IO/IOSample.cs
@@ -1,469 +1,496 @@
-using Kveer.XBeeApi.Exceptions;
-using Kveer.XBeeApi.Utils;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Kveer.XBeeApi.IO
-{
- ///
- /// This class represents an IO Data Sample. The sample is built using the the constructor. The sample contains an analog and digital mask indicating which IO lines are configured with that functionality.
- /// Depending on the protocol the XBee device is executing, the digital and analog masks are retrieved in separated bytes (2 bytes for the digital mask and 1 for the analog mask) or merged (digital and analog masks are contained in the same 2 bytes).
- ///
- /// 802.15.4 Protocol
- ///
- /// Digital and analog channels masks
- /// ------------------------------------------------------------------
- /// Indicates which digital and ADC IO lines are configured in the module. Each bit corresponds to one digital or ADC IO line on the module:
- ///
- /// bit 0 = DIO0 1
- /// bit 1 = DIO1 0
- /// bit 2 = DIO2 0
- /// bit 3 = DIO3 1
- /// bit 4 = DIO4 0
- /// bit 5 = DIO5 1
- /// bit 6 = DIO6 0
- /// bit 7 = DIO7 0
- /// bit 8 = DIO8 0
- /// bit 9 = AD0 0
- /// bit 10 = AD1 1
- /// bit 11 = AD2 1
- /// bit 12 = AD3 0
- /// bit 13 = AD4 0
- /// bit 14 = AD5 0
- /// bit 15 = N/A 0
- ///
- /// Example: mask of {@code 0x0C29} means DIO0, DIO3, DIO5, AD1 and AD2 enabled.
- /// 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 1
- ///
- /// Other Protocols
- ///
- /// Digital Channel Mask
- /// ------------------------------------------------------------------
- /// Indicates which digital IO lines are configured in the module. Each bit corresponds to one digital IO line on the module:
- ///
- /// bit 0 = DIO0/AD0
- /// bit 1 = DIO1/AD1
- /// bit 2 = DIO2/AD2
- /// bit 3 = DIO3/AD3
- /// bit 4 = DIO4/AD4
- /// bit 5 = DIO5/AD5/ASSOC
- /// bit 6 = DIO6/RTS
- /// bit 7 = DIO7/CTS
- /// bit 8 = DIO8/DTR/SLEEP_RQ
- /// bit 9 = DIO9/ON_SLEEP
- /// bit 10 = DIO10/PWM0/RSSI
- /// bit 11 = DIO11/PWM1
- /// bit 12 = DIO12/CD
- /// bit 13 = DIO13
- /// bit 14 = DIO14
- /// bit 15 = N/A
- ///
- /// Example: mask of {@code 0x040B} means DIO0, DIO1, DIO2, DIO3 and DIO10 enabled.
- /// 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1
- ///
- /// Analog Channel Mask
- /// -----------------------------------------------------------------------
- /// Indicates which lines are configured as ADC. Each bit in the analog channel mask corresponds to one ADC line on the module.
- ///
- /// bit 0 = AD0/DIO0
- /// bit 1 = AD1/DIO1
- /// bit 2 = AD2/DIO2
- /// bit 3 = AD3/DIO3
- /// bit 4 = AD4/DIO4
- /// bit 5 = AD5/DIO5/ASSOC
- /// bit 6 = N/A
- /// bit 7 = Supply Voltage Value
- ///
- /// Example: mask of {@code 0x03} means AD0, and AD1 enabled.
- /// 0 0 0 0 0 0 1 1
- ///
- public class IOSample
- { // Variables.
- private readonly byte[] ioSamplePayload;
-
- ///
- /// Gets the HSB of the digital mask.
- ///
- ///
- ///
- public int DigitalHSBMask { get; private set; }
-
- ///
- /// Gets the LSB of the digital mask.
- ///
- ///
- ///
- public int DigitalLSBMask { get; private set; }
-
- ///
- /// Gets the combined (HSB + LSB) digital mask.
- ///
- ///
- ///
- public int DigitalMask { get; private set; }
- public int AnalogMask { get; private set; }
- private int digitalHSBValues;
- private int digitalLSBValues;
- private int digitalValues;
- private int powerSupplyVoltage;
-
- private readonly IDictionary analogValuesMap = new Dictionary();
- private readonly IDictionary digitalValuesMap = new Dictionary();
-
- ///
- /// Instantiates a new object of type with the given IO sample payload.
- ///
- /// The payload corresponding to an IO sample.
- /// if length of is lower than 5.
- /// if is null.
- public IOSample(byte[] ioSamplePayload)
- {
- Contract.Requires(ioSamplePayload != null, "IO sample payload cannot be null.");
- Contract.Requires(ioSamplePayload.Length >= 5, "IO sample payload must be longer than 4.");
-
- this.ioSamplePayload = ioSamplePayload;
- if (ioSamplePayload.Length % 2 != 0)
- ParseRawIOSample();
- else
- ParseIOSample();
- }
-
- ///
- /// Parses the information contained in the IO sample bytes reading the value of each configured DIO and ADC.
- ///
- private void ParseRawIOSample()
- {
- int dataIndex = 3;
-
- // Obtain the digital mask. // Available digital IOs in 802.15.4
- DigitalHSBMask = ioSamplePayload[1] & 0x01; // 0 0 0 0 0 0 0 1
- DigitalLSBMask = ioSamplePayload[2] & 0xFF; // 1 1 1 1 1 1 1 1
- // Combine the masks.
- DigitalMask = (DigitalHSBMask << 8) + DigitalLSBMask;
- // Obtain the analog mask. // Available analog IOs in 802.15.4
- AnalogMask = ((ioSamplePayload[1] << 8) + (ioSamplePayload[2] & 0xFF)) & 0x7E00; // 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
-
- // Read the digital values (if any). There are 9 possible digital lines in
- // 802.15.4 protocol. The digital mask indicates if there is any digital
- // line enabled to read its value. If 0, no digital values are received.
- if (DigitalMask > 0)
- {
- // Obtain the digital values.
- digitalHSBValues = ioSamplePayload[3] & 0x7F;
- digitalLSBValues = ioSamplePayload[4] & 0xFF;
- // Combine the values.
- digitalValues = (digitalHSBValues << 8) + digitalLSBValues;
-
- for (int i = 0; i < 16; i++)
- {
- if (!ByteUtils.IsBitEnabled(DigitalMask, i))
- continue;
- if (ByteUtils.IsBitEnabled(digitalValues, i))
- digitalValuesMap.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.HIGH);
- else
- digitalValuesMap.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.LOW);
- }
- // Increase the data index to read the analog values.
- dataIndex += 2;
- }
-
- // Read the analog values (if any). There are 6 possible analog lines.
- // The analog mask indicates if there is any analog line enabled to read
- // its value. If 0, no analog values are received.
- int adcIndex = 9;
- while ((ioSamplePayload.Length - dataIndex) > 1 && adcIndex < 16)
- {
- if (!ByteUtils.IsBitEnabled(AnalogMask, adcIndex))
- {
- adcIndex += 1;
- continue;
- }
- // 802.15.4 protocol does not provide power supply value, so get just the ADC data.
- analogValuesMap.Add(IOLine.UNKNOWN.GetDIO(adcIndex - 9), ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF));
- // Increase the data index to read the next analog values.
- dataIndex += 2;
- adcIndex += 1;
- }
- }
-
- ///
- /// Parses the information contained in the IO sample bytes reading the value of each configured DIO and ADC.
- ///
- private void ParseIOSample()
- {
- int dataIndex = 4;
-
- // Obtain the digital masks. // Available digital IOs
- DigitalHSBMask = ioSamplePayload[1] & 0x7F; // 0 1 1 1 1 1 1 1
- DigitalLSBMask = ioSamplePayload[2] & 0xFF; // 1 1 1 1 1 1 1 1
- // Combine the masks.
- DigitalMask = (DigitalHSBMask << 8) + DigitalLSBMask;
- // Obtain the analog mask. // Available analog IOs
- AnalogMask = ioSamplePayload[3] & 0xBF; // 1 0 1 1 1 1 1 1
-
- // Read the digital values (if any). There are 16 possible digital lines.
- // The digital mask indicates if there is any digital line enabled to read
- // its value. If 0, no digital values are received.
- if (DigitalMask > 0)
- {
- // Obtain the digital values.
- digitalHSBValues = ioSamplePayload[4] & 0x7F;
- digitalLSBValues = ioSamplePayload[5] & 0xFF;
- // Combine the values.
- digitalValues = (digitalHSBValues << 8) + digitalLSBValues;
-
- for (int i = 0; i < 16; i++)
- {
- if (!ByteUtils.IsBitEnabled(DigitalMask, i))
- continue;
- if (ByteUtils.IsBitEnabled(digitalValues, i))
- digitalValuesMap.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.HIGH);
- else
- digitalValuesMap.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.LOW);
- }
- // Increase the data index to read the analog values.
- dataIndex += 2;
- }
-
- // Read the analog values (if any). There are 6 possible analog lines.
- // The analog mask indicates if there is any analog line enabled to read
- // its value. If 0, no analog values are received.
- int adcIndex = 0;
- while ((ioSamplePayload.Length - dataIndex) > 1 && adcIndex < 8)
- {
- if (!ByteUtils.IsBitEnabled(AnalogMask, adcIndex))
- {
- adcIndex += 1;
- continue;
- }
- // When analog index is 7, it means that the analog value corresponds to the power
- // supply voltage, therefore this value should be stored in a different value.
- if (adcIndex == 7)
- powerSupplyVoltage = ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF);
- else
- analogValuesMap.Add(IOLine.UNKNOWN.GetDIO(adcIndex), ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF));
- // Increase the data index to read the next analog values.
- dataIndex += 2;
- adcIndex += 1;
- }
- }
-
- ///
- /// Indicates whether or not the has digital values.
- ///
- /// true if there are digital values, false otherwise.
- public bool HasDigitalValues
- {
- get
- {
- return digitalValuesMap.Count > 0;
- }
- }
-
- ///
- /// Indicates whether the IO sample contains a digital value for the specified
- ///
- /// The IO line to check if has a digital value.
- /// true if the specified has a digital value, false otherwises.
- public bool HasDigitalValue(IOLine ioLine)
- {
- return digitalValuesMap.ContainsKey(ioLine);
- }
-
- ///
- /// Gets the digital values dictionary.
- ///
- /// To verify if this sample contains a valid digital values, use the method .
- /// if (ioSample.hasDigitalValues()) {
- /// var values = ioSample.getDigitalValues();
- /// ...
- /// } else {
- /// ...
- /// }
- /// }
- ///
- ///
- ///
- ///
- public IDictionary DigitalValues
- {
- get
- {
- return digitalValuesMap;
- }
- }
-
- ///
- /// Gets the digital value of the provided IO line.
- ///
- /// The IO line to get its digital value.
- /// The IOValue of the specified
- /// To verify if this sample contains a digital value for the specified , use the method .
- /// if (ioSample.hasDigitalValue(IOLine.DIO0_AD0)) {
- /// IOValue value = ioSample.getDigitalValue(IOLine.DIO0_AD0);
- /// ...
- /// } else {
- /// ...
- /// }
- /// }
- ///
- ///
- ///
- ///
- ///
- public IOValue GetDigitalValue(IOLine ioLine)
- {
- if (!digitalValuesMap.ContainsKey(ioLine))
- return IOValue.UNKNOWN;
- return digitalValuesMap[ioLine];
- }
-
- ///
- /// Indicates whether the IOSample has analog values.
- ///
- ///
- ///
- ///
- ///
- public bool HasAnalogValues
- {
- get
- {
- return analogValuesMap.Count > 0;
- }
- }
-
- ///
- /// Indicates whether or not the specified has an analog value.
- ///
- /// The IO line to check if has an analog value.
- /// true if the specified has an analog value, false otherwise.
- ///
- ///
- ///
- ///
- public bool HasAnalogValue(IOLine ioLine)
- {
- return analogValuesMap.ContainsKey(ioLine);
- }
-
- ///
- /// Gets the analog values dictionary.
- ///
- /// To verify if this sample contains a valid analog values, use the method .
- /// if (ioSample.hasAnalogValues()) {
- /// var values = ioSample.AnalogValues();
- /// ...
- /// } else {
- /// ...
- /// }
- /// }
- ///
- ///
- ///
- ///
- public IDictionary AnalogValues
- {
- get
- {
- return analogValuesMap;
- }
- }
-
- ///
- /// Gets the analog value of the specified .
- ///
- /// To verify if this sample contains an analog value for the specified , use the method .
- /// if (ioSample.hasAnalogValue(IOLine.DIO0_AD0)) {
- /// var value = ioSample.GetAnalogValue(IOLine.DIO0_AD0);
- /// ...
- /// } else {
- /// ...
- /// }
- /// }
- /// The IO line to get its analog value.
- /// The analog value of the given IO line.
- ///
- ///
- ///
- ///
- public int GetAnalogValue(IOLine ioLine)
- {
- if (!analogValuesMap.ContainsKey(ioLine))
- return int.MaxValue;
-
- return analogValuesMap[ioLine];
- }
-
- ///
- /// Indicates whether the IOSample has power supply value.
- ///
- ///
- public bool HasPowerSupplyValue
- {
- get
- {
- return ByteUtils.IsBitEnabled(AnalogMask, 7);
- }
- }
-
- ///
- /// Gets the value of the power supply voltage.
- ///
- /// To verify if this sample contains the power supply voltage, use the method .
- /// if (ioSample.hasPowerSupplyValue()) {
- /// int value = ioSample.PowerSupplyValue;
- /// ...
- /// } else {
- /// ...
- /// }
- /// }
- ///
- public int PowerSupplyValue
- {
- get
- {
- if (!ByteUtils.IsBitEnabled(AnalogMask, 7))
- throw new OperationNotSupportedException();
- return powerSupplyVoltage;
- }
- }
-
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder("{");
- if (HasDigitalValues)
- {
- foreach (IOLine line in digitalValuesMap.Keys)
- {
- sb.Append("[").Append(line).Append(": ").Append(digitalValuesMap[line]).Append("], ");
- }
- }
- if (HasAnalogValues)
- {
- foreach (IOLine line in analogValuesMap.Keys)
- {
- sb.Append("[").Append(line).Append(": ").Append(analogValuesMap[line]).Append("], ");
- }
- }
- if (HasPowerSupplyValue)
- {
- try
- {
- sb.Append("[").Append("Power supply voltage: ").Append(PowerSupplyValue).Append("], ");
- }
- catch (OperationNotSupportedException ) { }
- }
-
- String s = sb.ToString();
- if (s.EndsWith(", "))
- s = s.Substring(0, s.Length - 2);
- return s + "}";
- }
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.IO
+{
+ ///
+ /// This class represents an IO Data Sample.
+ ///
+ /// The sample is built using the the constructor. The sample contains an analog and
+ /// digital mask indicating which IO lines are configured with that functionality.
+ /// Depending on the protocol the XBee device is executing, the digital and analog masks are
+ /// retrieved in separated bytes (2 bytes for the digital mask and 1 for the analog mask) or
+ /// merged (digital and analog masks are contained in the same 2 bytes).
+ ///
+ /// 802.15.4 Protocol
+ ///
+ /// Digital and analog channels masks
+ /// ------------------------------------------------------------------
+ /// Indicates which digital and ADC IO lines are configured in the module. Each bit corresponds
+ /// to one digital or ADC IO line on the module:
+ ///
+ /// bit 0 = DIO0 1
+ /// bit 1 = DIO1 0
+ /// bit 2 = DIO2 0
+ /// bit 3 = DIO3 1
+ /// bit 4 = DIO4 0
+ /// bit 5 = DIO5 1
+ /// bit 6 = DIO6 0
+ /// bit 7 = DIO7 0
+ /// bit 8 = DIO8 0
+ /// bit 9 = AD0 0
+ /// bit 10 = AD1 1
+ /// bit 11 = AD2 1
+ /// bit 12 = AD3 0
+ /// bit 13 = AD4 0
+ /// bit 14 = AD5 0
+ /// bit 15 = N/A 0
+ ///
+ /// Example: mask of {@code 0x0C29} means DIO0, DIO3, DIO5, AD1 and AD2 enabled.
+ /// 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 1
+ ///
+ /// Other Protocols
+ ///
+ /// Digital Channel Mask
+ /// ------------------------------------------------------------------
+ /// Indicates which digital IO lines are configured in the module. Each bit corresponds to one
+ /// digital IO line on the module:
+ ///
+ /// bit 0 = DIO0/AD0
+ /// bit 1 = DIO1/AD1
+ /// bit 2 = DIO2/AD2
+ /// bit 3 = DIO3/AD3
+ /// bit 4 = DIO4/AD4
+ /// bit 5 = DIO5/AD5/ASSOC
+ /// bit 6 = DIO6/RTS
+ /// bit 7 = DIO7/CTS
+ /// bit 8 = DIO8/DTR/SLEEP_RQ
+ /// bit 9 = DIO9/ON_SLEEP
+ /// bit 10 = DIO10/PWM0/RSSI
+ /// bit 11 = DIO11/PWM1
+ /// bit 12 = DIO12/CD
+ /// bit 13 = DIO13
+ /// bit 14 = DIO14
+ /// bit 15 = N/A
+ ///
+ /// Example: mask of {@code 0x040B} means DIO0, DIO1, DIO2, DIO3 and DIO10 enabled.
+ /// 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1
+ ///
+ /// Analog Channel Mask
+ /// -----------------------------------------------------------------------
+ /// Indicates which lines are configured as ADC. Each bit in the analog channel mask corresponds to
+ /// one ADC line on the module.
+ ///
+ /// bit 0 = AD0/DIO0
+ /// bit 1 = AD1/DIO1
+ /// bit 2 = AD2/DIO2
+ /// bit 3 = AD3/DIO3
+ /// bit 4 = AD4/DIO4
+ /// bit 5 = AD5/DIO5/ASSOC
+ /// bit 6 = N/A
+ /// bit 7 = Supply Voltage Value
+ ///
+ /// Example: mask of {@code 0x03} means AD0, and AD1 enabled.
+ /// 0 0 0 0 0 0 1 1
+ ///
+ public class IOSample
+ {
+ // Variables.
+ private readonly byte[] ioSamplePayload;
+
+ private int digitalHSBValues;
+ private int digitalLSBValues;
+ private int digitalValues;
+ private int powerSupplyVoltage;
+
+ ///
+ /// Instantiates a new object of type with the given IO sample payload.
+ ///
+ /// The payload corresponding to an IO sample.
+ /// If length of is lower
+ /// than 5.
+ /// If is null.
+ public IOSample(byte[] ioSamplePayload)
+ {
+ if (ioSamplePayload == null)
+ throw new ArgumentNullException("IO sample payload cannot be null.");
+ if (ioSamplePayload.Length < 5)
+ throw new ArgumentException("IO sample payload must be longer than 4.");
+
+ this.ioSamplePayload = ioSamplePayload;
+ if (ioSamplePayload.Length % 2 != 0)
+ ParseRawIOSample();
+ else
+ ParseIOSample();
+ }
+
+ // Properties.
+ ///
+ /// Gets the HSB of the digital mask.
+ ///
+ ///
+ ///
+ public int DigitalHSBMask { get; private set; }
+
+ ///
+ /// Gets the LSB of the digital mask.
+ ///
+ ///
+ ///
+ public int DigitalLSBMask { get; private set; }
+
+ ///
+ /// The combined (HSB + LSB) digital mask.
+ ///
+ ///
+ ///
+ public int DigitalMask { get; private set; }
+
+ ///
+ /// The analog mask.
+ ///
+ public int AnalogMask { get; private set; }
+
+ ///
+ /// The digital values dictionary.
+ ///
+ /// To verify if this sample contains a valid digital values, use the method .
+ /// if (ioSample.hasDigitalValues()) {
+ /// var values = ioSample.DigitalValues;
+ /// ...
+ /// } else {
+ /// ...
+ /// }
+ /// }
+ ///
+ ///
+ ///
+ ///
+ public IDictionary DigitalValues { get; } = new Dictionary();
+
+ ///
+ /// Indicates whether or not the has digital values.
+ ///
+ /// true if there are digital values, false otherwise.
+ public bool HasDigitalValues
+ {
+ get
+ {
+ return DigitalValues.Count > 0;
+ }
+ }
+
+ ///
+ /// The analog values dictionary.
+ ///
+ /// To verify if this sample contains a valid analog values, use the property
+ /// .
+ /// if (ioSample.HasAnalogValues()) {
+ /// var values = ioSample.AnalogValues;
+ /// ...
+ /// } else {
+ /// ...
+ /// }
+ /// }
+ ///
+ ///
+ ///
+ ///
+ public IDictionary AnalogValues { get; } = new Dictionary();
+
+ ///
+ /// Indicates whether the IOSample has analog values.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public bool HasAnalogValues
+ {
+ get
+ {
+ return AnalogValues.Count > 0;
+ }
+ }
+
+ ///
+ /// Indicates whether the IOSample has power supply value.
+ ///
+ ///
+ public bool HasPowerSupplyValue
+ {
+ get
+ {
+ return ByteUtils.IsBitEnabled(AnalogMask, 7);
+ }
+ }
+
+ ///
+ /// Gets the value of the power supply voltage.
+ ///
+ /// To verify if this sample contains the power supply voltage, use the property
+ /// .
+ /// if (ioSample.HasPowerSupplyValue) {
+ /// int value = ioSample.PowerSupplyValue;
+ /// ...
+ /// } else {
+ /// ...
+ /// }
+ /// }
+ /// If the IOSample does not have power supply
+ /// value.
+ ///
+ public int PowerSupplyValue
+ {
+ get
+ {
+ if (!ByteUtils.IsBitEnabled(AnalogMask, 7))
+ throw new OperationNotSupportedException();
+ return powerSupplyVoltage;
+ }
+ }
+
+ ///
+ /// Indicates whether the IO sample contains a digital value for the specified
+ ///
+ /// The IO line to check if has a digital value.
+ /// true if the specified has a digital value, false
+ /// otherwises.
+ public bool HasDigitalValue(IOLine ioLine)
+ {
+ return DigitalValues.ContainsKey(ioLine);
+ }
+
+ ///
+ /// Gets the digital value of the provided IO line.
+ ///
+ /// The IO line to get its digital value.
+ /// The IOValue of the specified
+ /// To verify if this sample contains a digital value for the
+ /// specified , use the method .
+ /// if (ioSample.HasDigitalValue(IOLine.DIO0_AD0)) {
+ /// IOValue value = ioSample.GetDigitalValue(IOLine.DIO0_AD0);
+ /// ...
+ /// } else {
+ /// ...
+ /// }
+ /// }
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IOValue GetDigitalValue(IOLine ioLine)
+ {
+ if (!DigitalValues.ContainsKey(ioLine))
+ return IOValue.UNKNOWN;
+ return DigitalValues[ioLine];
+ }
+
+ ///
+ /// Indicates whether or not the specified has an analog value.
+ ///
+ /// The IO line to check if has an analog value.
+ /// true if the specified has an analog value,
+ /// false otherwise.
+ ///
+ ///
+ ///
+ ///
+ public bool HasAnalogValue(IOLine ioLine)
+ {
+ return AnalogValues.ContainsKey(ioLine);
+ }
+
+ ///
+ /// Gets the analog value of the specified .
+ ///
+ /// To verify if this sample contains an analog value for the specified
+ /// , use the method .
+ /// if (ioSample.HasAnalogValue(IOLine.DIO0_AD0)) {
+ /// var value = ioSample.GetAnalogValue(IOLine.DIO0_AD0);
+ /// ...
+ /// } else {
+ /// ...
+ /// }
+ /// }
+ /// The IO line to get its analog value.
+ /// The analog value of the given IO line.
+ ///
+ ///
+ ///
+ ///
+ public int GetAnalogValue(IOLine ioLine)
+ {
+ if (!AnalogValues.ContainsKey(ioLine))
+ return int.MaxValue;
+
+ return AnalogValues[ioLine];
+ }
+
+ ///
+ /// Returns the string representation of this IO Sample.
+ ///
+ /// The string representation of this IO Sample.
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder("{");
+ if (HasDigitalValues)
+ {
+ foreach (IOLine line in DigitalValues.Keys)
+ {
+ sb.Append("[").Append(line).Append(": ").Append(DigitalValues[line]).Append("], ");
+ }
+ }
+ if (HasAnalogValues)
+ {
+ foreach (IOLine line in AnalogValues.Keys)
+ {
+ sb.Append("[").Append(line).Append(": ").Append(AnalogValues[line]).Append("], ");
+ }
+ }
+ if (HasPowerSupplyValue)
+ {
+ try
+ {
+ sb.Append("[").Append("Power supply voltage: ").Append(PowerSupplyValue).Append("], ");
+ }
+ catch (OperationNotSupportedException) { }
+ }
+
+ string s = sb.ToString();
+ if (s.EndsWith(", "))
+ s = s.Substring(0, s.Length - 2);
+ return s + "}";
+ }
+
+ ///
+ /// Parses the information contained in the IO sample bytes reading the value of each configured
+ /// DIO and ADC.
+ ///
+ private void ParseRawIOSample()
+ {
+ int dataIndex = 3;
+
+ // Obtain the digital mask. // Available digital IOs in 802.15.4
+ DigitalHSBMask = ioSamplePayload[1] & 0x01; // 0 0 0 0 0 0 0 1
+ DigitalLSBMask = ioSamplePayload[2] & 0xFF; // 1 1 1 1 1 1 1 1
+ // Combine the masks.
+ DigitalMask = (DigitalHSBMask << 8) + DigitalLSBMask;
+ // Obtain the analog mask. // Available analog IOs in 802.15.4
+ AnalogMask = ((ioSamplePayload[1] << 8) + (ioSamplePayload[2] & 0xFF)) & 0x7E00; // 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0
+
+ // Read the digital values (if any). There are 9 possible digital lines in 802.15.4 protocol. The
+ // digital mask indicates if there is any digital line enabled to read its value. If 0, no digital
+ // values are received.
+ if (DigitalMask > 0)
+ {
+ // Obtain the digital values.
+ digitalHSBValues = ioSamplePayload[3] & 0x7F;
+ digitalLSBValues = ioSamplePayload[4] & 0xFF;
+ // Combine the values.
+ digitalValues = (digitalHSBValues << 8) + digitalLSBValues;
+
+ for (int i = 0; i < 16; i++)
+ {
+ if (!ByteUtils.IsBitEnabled(DigitalMask, i))
+ continue;
+ if (ByteUtils.IsBitEnabled(digitalValues, i))
+ DigitalValues.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.HIGH);
+ else
+ DigitalValues.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.LOW);
+ }
+ // Increase the data index to read the analog values.
+ dataIndex += 2;
+ }
+
+ // Read the analog values (if any). There are 6 possible analog lines. The analog mask indicates
+ // if there is any analog line enabled to read its value. If 0, no analog values are received.
+ int adcIndex = 9;
+ while ((ioSamplePayload.Length - dataIndex) > 1 && adcIndex < 16)
+ {
+ if (!ByteUtils.IsBitEnabled(AnalogMask, adcIndex))
+ {
+ adcIndex += 1;
+ continue;
+ }
+ // 802.15.4 protocol does not provide power supply value, so get just the ADC data.
+ AnalogValues.Add(IOLine.UNKNOWN.GetDIO(adcIndex - 9), ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF));
+ // Increase the data index to read the next analog values.
+ dataIndex += 2;
+ adcIndex += 1;
+ }
+ }
+
+ ///
+ /// Parses the information contained in the IO sample bytes reading the value of each configured
+ /// DIO and ADC.
+ ///
+ private void ParseIOSample()
+ {
+ int dataIndex = 4;
+
+ // Obtain the digital masks. // Available digital IOs
+ DigitalHSBMask = ioSamplePayload[1] & 0x7F; // 0 1 1 1 1 1 1 1
+ DigitalLSBMask = ioSamplePayload[2] & 0xFF; // 1 1 1 1 1 1 1 1
+ // Combine the masks.
+ DigitalMask = (DigitalHSBMask << 8) + DigitalLSBMask;
+ // Obtain the analog mask. // Available analog IOs
+ AnalogMask = ioSamplePayload[3] & 0xBF; // 1 0 1 1 1 1 1 1
+
+ // Read the digital values (if any). There are 16 possible digital lines. The digital mask indicates
+ // if there is any digital line enabled to read its value. If 0, no digital values are received.
+ if (DigitalMask > 0)
+ {
+ // Obtain the digital values.
+ digitalHSBValues = ioSamplePayload[4] & 0x7F;
+ digitalLSBValues = ioSamplePayload[5] & 0xFF;
+ // Combine the values.
+ digitalValues = (digitalHSBValues << 8) + digitalLSBValues;
+
+ for (int i = 0; i < 16; i++)
+ {
+ if (!ByteUtils.IsBitEnabled(DigitalMask, i))
+ continue;
+ if (ByteUtils.IsBitEnabled(digitalValues, i))
+ DigitalValues.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.HIGH);
+ else
+ DigitalValues.Add(IOLine.UNKNOWN.GetDIO(i), IOValue.LOW);
+ }
+ // Increase the data index to read the analog values.
+ dataIndex += 2;
+ }
+
+ // Read the analog values (if any). There are 6 possible analog lines. The analog mask indicates
+ // if there is any analog line enabled to read its value. If 0, no analog values are received.
+ int adcIndex = 0;
+ while ((ioSamplePayload.Length - dataIndex) > 1 && adcIndex < 8)
+ {
+ if (!ByteUtils.IsBitEnabled(AnalogMask, adcIndex))
+ {
+ adcIndex += 1;
+ continue;
+ }
+ // When analog index is 7, it means that the analog value corresponds to the power
+ // supply voltage, therefore this value should be stored in a different value.
+ if (adcIndex == 7)
+ powerSupplyVoltage = ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF);
+ else
+ AnalogValues.Add(IOLine.UNKNOWN.GetDIO(adcIndex), ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF));
+ // Increase the data index to read the next analog values.
+ dataIndex += 2;
+ adcIndex += 1;
+ }
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/IO/IOValue.cs b/XBeeLibrary.Core/IO/IOValue.cs
new file mode 100644
index 0000000..a9586f7
--- /dev/null
+++ b/XBeeLibrary.Core/IO/IOValue.cs
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XBeeLibrary.Core.IO
+{
+ ///
+ /// Enumerates the possible values of a configured as digital I/O.
+ ///
+ ///
+ public enum IOValue
+ {
+ // Enumeration types.
+ UNKNOWN = 0,
+ LOW = 4,
+ HIGH = 5
+ }
+
+ public static class IOValueExtensions
+ {
+ private static IDictionary lookupTable = new Dictionary();
+
+ static IOValueExtensions()
+ {
+ lookupTable.Add(IOValue.LOW, "Low");
+ lookupTable.Add(IOValue.HIGH, "High");
+ }
+
+ ///
+ /// Gets the ID of the IO value.
+ ///
+ ///
+ /// The ID of the IO value
+ public static int GetID(this IOValue source)
+ {
+ return (int)source;
+ }
+
+ ///
+ /// Gets the name of the IO value.
+ ///
+ ///
+ /// The name of the IO value.
+ public static string GetName(this IOValue source)
+ {
+ return source.ToString();
+ }
+
+ ///
+ /// Gets the associated with the given .
+ ///
+ ///
+ /// The ID corresponding to the to retrieve.
+ /// The associated with the given .
+ public static IOValue GetIOValue(this IOValue source, int valueID)
+ {
+ if (Enum.GetValues(typeof(IOValue)).OfType().Contains(valueID))
+ return (IOValue)valueID;
+
+ return IOValue.UNKNOWN;
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/IPDevice.cs b/XBeeLibrary.Core/IPDevice.cs
new file mode 100644
index 0000000..f53d822
--- /dev/null
+++ b/XBeeLibrary.Core/IPDevice.cs
@@ -0,0 +1,953 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Net;
+using XBeeLibrary.Core.Connection;
+using XBeeLibrary.Core.Events;
+using XBeeLibrary.Core.Events.Relay;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.Models;
+using XBeeLibrary.Core.Packet;
+using XBeeLibrary.Core.Packet.IP;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core
+{
+ ///
+ /// This class provides common functionality for XBee IP devices.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public class IPDevice : AbstractXBeeDevice
+ {
+ // Constants.
+ private const string BROADCAST_IP = "255.255.255.255";
+
+ protected const short DEFAULT_SOURCE_PORT = 9750;
+
+ protected const IPProtocol DEFAULT_PROTOCOL = IPProtocol.TCP;
+
+ // Variables.
+ protected IPAddress ipAddress;
+
+ protected int sourcePort = DEFAULT_SOURCE_PORT;
+
+ ///
+ /// Class constructor. Instantiates a new object in the given connection
+ /// interface.
+ ///
+ /// The connection interface with the physical IP device.
+ /// If == null.
+ ///
+ ///
+ ///
+ public IPDevice(IConnectionInterface connectionInterface)
+ : base(connectionInterface) { }
+
+ // Events.
+ ///
+ /// Represents the method that will handle the Data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public virtual new event EventHandler PacketReceived
+ {
+ add
+ {
+ base.PacketReceived += value;
+ }
+ remove
+ {
+ base.PacketReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the Modem status received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler ModemStatusReceived
+ {
+ add
+ {
+ base.ModemStatusReceived += value;
+ }
+ remove
+ {
+ base.ModemStatusReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the User Data Relay received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler UserDataRelayReceived
+ {
+ add
+ {
+ base.UserDataRelayReceived += value;
+ }
+ remove
+ {
+ base.UserDataRelayReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the Bluetooth data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler BluetoothDataReceived
+ {
+ add
+ {
+ base.BluetoothDataReceived += value;
+ }
+ remove
+ {
+ base.BluetoothDataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the MicroPython data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler MicroPythonDataReceived
+ {
+ add
+ {
+ base.MicroPythonDataReceived += value;
+ }
+ remove
+ {
+ base.MicroPythonDataReceived -= value;
+ }
+ }
+
+ ///
+ /// Represents the method that will handle the IP data received event.
+ ///
+ /// If the event handler is null.
+ ///
+ public new event EventHandler IPDataReceived
+ {
+ add
+ {
+ base.IPDataReceived += value;
+ }
+ remove
+ {
+ base.IPDataReceived -= value;
+ }
+ }
+
+ // Properties.
+ ///
+ /// The IP address of this IP device.
+ ///
+ public IPAddress IPAddress { get; private set; }
+
+ ///
+ /// The 16-bit address of this XBee device. IP devices don't have a 16-bit address, so this
+ /// property returns null.
+ ///
+ /// To refresh this value, use the
+ /// method.
+ ///
+ public override XBee16BitAddress XBee16BitAddr
+ {
+ get
+ {
+ // IP modules do not have 16-bit address.
+ return null;
+ }
+ }
+
+ ///
+ /// The Operating mode (AT, API or API escaped) of this XBee device for a local device,
+ /// and the operating mode of the local device used as communication interface for a remote device.
+ ///
+ ///
+ ///
+ public new OperatingMode OperatingMode
+ {
+ get
+ {
+ return base.OperatingMode;
+ }
+ }
+
+ ///
+ /// The status of the connection interface associated to this device. It indicates if the connection
+ /// is open or not.
+ ///
+ ///
+ ///
+ public new bool IsOpen => base.IsOpen;
+
+ ///
+ /// Always false, since this is always a local device.
+ ///
+ public override bool IsRemote => false;
+
+ ///
+ /// The XBee device timeout in milliseconds for received packets in synchronous operations.
+ ///
+ /// If the value to be set is lesser than 0.
+ public new int ReceiveTimeout
+ {
+ get
+ {
+ return base.ReceiveTimeout;
+ }
+ set
+ {
+ base.ReceiveTimeout = value;
+ }
+ }
+
+ ///
+ /// Opens the connection interface associated with this XBee device.
+ ///
+ /// When opening the device an information reading process is automatically performed.
+ /// This includes:
+ ///
+ /// - 64-bit address.
+ /// - Node Identifier.
+ /// - Hardware version
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - 16-bit address (not for DigiMesh modules).
+ ///
+ /// If this device connection is already open.
+ /// If the operating mode of the device is
+ /// or
+ /// If the BLE authentication process fails.
+ /// If the timeout to read settings when initializing the
+ /// device elapses without response.
+ /// If there is any problem opening this device connection.
+ ///
+ ///
+ public virtual new void Open()
+ {
+ base.Open();
+ }
+
+ ///
+ /// Closes the connection interface associated with this XBee device.
+ ///
+ ///
+ ///
+ public new void Close()
+ {
+ base.Close();
+ }
+
+ ///
+ /// Gets the destination IP address.
+ ///
+ /// The destination IP address.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the given command.
+ /// If there is any other XBee related error.
+ ///
+ public IPAddress GetDestinationIPAddress()
+ {
+ return new IPAddress(GetParameter("DL"));
+ }
+
+ ///
+ /// Sets the Destination IP address.
+ ///
+ /// The new destination of the device.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set configuration command.
+ /// If there is any other XBee related error.
+ ///
+ public void SetDestinationIPAddress(IPAddress destAddress)
+ {
+ if (destAddress == null)
+ throw new ArgumentNullException("Destination IP address cannot be null.");
+ SetParameter("DL", destAddress.GetAddressBytes());
+ }
+
+ ///
+ /// Reads some parameters from this device and obtains its protocol.
+ ///
+ /// This method refresh the values of:
+ ///
+ /// - 64-bit address only if it is not initialized.
+ /// - Node Identifier.
+ /// - Hardware version if it is not initialized.
+ /// - Firmware version.
+ /// - XBee device protocol.
+ /// - IP address.
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout reading the parameters.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ public override void ReadDeviceInfo()
+ {
+ base.ReadDeviceInfo();
+
+ // Read the module's IP address.
+ byte[] response = GetParameter("MY");
+ IPAddress = new IPAddress(response);
+ }
+
+ ///
+ /// Gets the next Frame ID of this XBee device.
+ ///
+ /// The next Frame ID.
+ public new byte GetNextFrameID()
+ {
+ return base.GetNextFrameID();
+ }
+
+ ///
+ /// Sends the provided data to the given XBee local interface.
+ ///
+ /// Destination XBee local interface.
+ /// Data to send.
+ /// If the destination interface is unknown.
+ /// If there is any XBee related error sending the User
+ /// Data Relay.
+ ///
+ ///
+ ///
+ public new void SendUserDataRelay(XBeeLocalInterface destinationInterface, byte[] data)
+ {
+ base.SendUserDataRelay(destinationInterface, data);
+ }
+
+ ///
+ /// Sends the given data to the XBee Bluetooth interface in a User Data Relay frame.
+ ///
+ /// Data to send.
+ /// If there is any XBee related error sending the Bluetooth
+ /// data.
+ ///
+ ///
+ public new void SendBluetoothData(byte[] data)
+ {
+ base.SendBluetoothData(data);
+ }
+
+ ///
+ /// Sends the given data to the XBee MicroPython interface in a User Data Relay frame.
+ ///
+ /// Data to send.
+ /// If there is any XBee related error sending the
+ /// MicroPython data.
+ ///
+ ///
+ public new void SendMicroPythonData(byte[] data)
+ {
+ base.SendMicroPythonData(data);
+ }
+
+ ///
+ /// Sends the given XBee packet and registers the given packet handler (if not null) to
+ /// manage what happens when the answers is received.
+ ///
+ /// This is a non-blocking operation. To wait for the answer use
+ /// .
+ /// XBee packet to be sent.
+ /// Event handler for the operation, null not to be notified when
+ /// the answer arrives.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ public new void SendPacket(XBeePacket packet, EventHandler handler)
+ {
+ base.SendPacket(packet, handler);
+ }
+
+ ///
+ /// Sends the given XBee packet asynchronously.
+ ///
+ /// To be notified when the answer is received, use the
+ /// event handler.
+ /// The XBee packet to be sent asynchronously.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ public new void SendPacketAsync(XBeePacket packet)
+ {
+ base.SendPacketAsync(packet);
+ }
+
+ ///
+ /// Sends the given XBee packet synchronously and blocks until the response is received or
+ /// the configured receive timeout expires.
+ ///
+ /// The receive timeout is consulted/configured using the property.
+ ///
+ /// Use or
+ /// for non-blocking
+ /// operations.
+ /// The XBee packet to be sent.
+ /// An object containing the response of the sent packet or
+ /// null if there is no response.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the operating mode is different from
+ /// and .
+ /// If the configured time expires while waiting for the
+ /// packet reply.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ public new XBeePacket SendPacket(XBeePacket packet)
+ {
+ return base.SendPacket(packet);
+ }
+
+ ///
+ /// Performs a software reset on this XBee device and blocks until the process is
+ /// completed.
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout resetting the device.
+ /// If there is any other XBee related error.
+ public override void Reset()
+ {
+ SoftwareReset();
+ }
+
+ ///
+ /// Reads a new User Data Relay packet received by this XBee device during the configured receive
+ /// timeout.
+ ///
+ /// This method blocks until new User Data Relay is received or the configured receive
+ /// timeout expires.
+ /// A object containing the source interface and data.
+ /// null if this device did not receive new User Data Relay during the configured receive
+ /// timeout.
+ /// If the interface is not open.
+ ///
+ public new UserDataRelayMessage ReadUserDataRelay()
+ {
+ return base.ReadUserDataRelay();
+ }
+
+ ///
+ /// Reads a new User Data Relay packet received by this XBee device during the provided timeout.
+ ///
+ /// This method blocks until new User Data Relay is received or the given timeout
+ /// expires.
+ /// The time to wait for new User Data Relay in
+ /// milliseconds.
+ /// A object containing the source interface and data.
+ /// null if this device did not receive new User Data Relay during
+ /// milliseconds.
+ /// If the interface is not open.
+ ///
+ public new UserDataRelayMessage ReadUserDataRelay(int timeout)
+ {
+ return base.ReadUserDataRelay(timeout);
+ }
+
+ ///
+ /// Starts listening for incoming IP transmissions in the provided port.
+ ///
+ /// Port to listen for incoming transmissions.
+ /// If 0
+ /// or if ]]> 65535.
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set configuration command.
+ /// If there is any other XBee related error.
+ public void StartListening(int sourcePort)
+ {
+ if (sourcePort < 0 || sourcePort > 65535)
+ throw new ArgumentException("Source port must be between 0 and 65535.");
+
+ SetParameter("C0", ByteUtils.ShortToByteArray((short)sourcePort));
+ this.sourcePort = sourcePort;
+ }
+
+ ///
+ /// Stops listening for incoming IP transmissions.
+ ///
+ /// If this device connection is not open.
+ /// If there is a timeout sending the set configuration command.
+ /// If there is any other XBee related error.
+ public void StopListening()
+ {
+ SetParameter("C0", ByteUtils.ShortToByteArray((short)0));
+ sourcePort = 0;
+ }
+
+ ///
+ /// Sends the provided IP data to the given IP address and port using the specified IP protocol. For
+ /// TCP and TCP SSL protocols, you can also indicate if the socket should be closed when data is sent.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ ///
+ /// For non-blocking operations use the method
+ /// .
+ /// The IP address to send IP data to.
+ /// The destination port of the transmission.
+ /// The IP protocol used for the transmission.
+ /// true to close the socket just after the transmission. false
+ /// to keep it open.
+ /// Byte array containing the IP data to be sent.
+ /// If 0
+ /// or if ]]> 65535
+ /// or if == .
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sendting the
+ /// data is not an instance of
+ /// or if its transmit status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SendIPData(IPAddress ipAddress, int destPort, IPProtocol protocol, bool closeSocket, byte[] data)
+ {
+ SendIPDataImpl(ipAddress, destPort, protocol, closeSocket, data);
+ }
+
+ ///
+ /// Sends the provided IP data to the given IP address and port using the specified IP protocol.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ ///
+ /// For non-blocking operations use the method
+ /// .
+ /// The IP address to send IP data to.
+ /// The destination port of the transmission.
+ /// The IP protocol used for the transmission.
+ /// Byte array containing the IP data to be sent.
+ /// If 0
+ /// or if ]]> 65535
+ /// or if == .
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sendting the
+ /// data is not an instance of
+ /// or if its transmit status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SendIPData(IPAddress ipAddress, int destPort, IPProtocol protocol, byte[] data)
+ {
+ SendIPDataImpl(ipAddress, destPort, protocol, false, data);
+ }
+
+ ///
+ /// Sends the provided IP data to the given IP address and port asynchronously using the specified
+ /// IP protocol. For TCP and TCP SSL protocols, you can also indicate if the socket should be closed
+ /// when data is sent.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for transmit
+ /// status packet.
+ /// The IP address to send IP data to.
+ /// The destination port of the transmission.
+ /// The IP protocol used for the transmission.
+ /// true to close the socket just after the transmission. false
+ /// to keep it open.
+ /// Byte array containing the IP data to be sent.
+ /// If 0
+ /// or if ]]> 65535
+ /// or if == .
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SendIPDataAsync(IPAddress ipAddress, int destPort, IPProtocol protocol, bool closeSocket, byte[] data)
+ {
+ SendIPDataAsyncImpl(ipAddress, destPort, protocol, closeSocket, data);
+ }
+
+ ///
+ /// Sends the provided IP data to the given IP address and port asynchronously using the
+ /// specified IP protocol.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for
+ /// transmit status packet.
+ /// The IP address to send IP data to.
+ /// The destination port of the transmission.
+ /// The IP protocol used for the transmission.
+ /// Byte array containing the IP data to be sent.
+ /// If 0
+ /// or if ]]> 65535
+ /// or if == .
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SendIPDataAsync(IPAddress ipAddress, int destPort, IPProtocol protocol, byte[] data)
+ {
+ SendIPDataAsyncImpl(ipAddress, destPort, protocol, false, data);
+ }
+
+ ///
+ /// Sends the provided IP data to all clients.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ /// The destination port of the transmission.
+ /// Byte array containing the IP data to be sent.
+ /// If 0
+ /// or if ]]> 65535.
+ /// If == null.
+ /// If this device connection is not open.
+ /// If the device is remote.
+ /// If the transmit status generated when sending
+ /// the packet is not an instance of
+ /// or if its transmit status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void SendBroadcastIPData(int destPort, byte[] data)
+ {
+ SendIPData(IPAddress.Parse(BROADCAST_IP), destPort, IPProtocol.UDP, false, data);
+ }
+
+ ///
+ /// Reads new IP data received by this XBee device during the configured receive timeout.
+ ///
+ /// This method blocks until new IP data is received or the configured receive
+ /// timeout expires.
+ ///
+ /// The receive timeout can be consulted/configured using the
+ /// property.
+ ///
+ /// Before reading IP data you need to start listening for incoming IP data at a specific port.
+ /// Use the method for that purpose. When finished, you can use
+ /// the method to stop listening for incoming IP data.
+ /// An object containing the IP data and the IP address that
+ /// sent the data. null if this did not receive new IP data during the configured receive
+ /// timeout.
+ /// If this device connection is not open.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public IPMessage ReadIPData()
+ {
+ return ReadIPDataPacket(null, TIMEOUT_READ_PACKET);
+ }
+
+ ///
+ /// Reads new IP data received by this XBee device during the provided timeout.
+ ///
+ /// This method blocks until new IP data is received or the configured receive
+ /// timeout expires.
+ /// A object containing the IP data and the IP address that
+ /// sent the data. null if this did not receive new IP data during timeout
+ /// milliseconds.
+ /// The time to wait for new IP data in milliseconds.
+ /// If 0.
+ /// If this device connection is not open.
+ ///
+ public IPMessage ReadIPData(int timeout)
+ {
+ if (timeout < 0)
+ throw new ArgumentException("Read timeout must be 0 or greater.");
+ return ReadIPDataPacket(null, timeout);
+ }
+
+ ///
+ /// Reads new IP data received from the given IP address during the configured receive timeout.
+ ///
+ /// This method blocks until new IP data is received or the configured receive timeout
+ /// expires.
+ /// A object containing the IP data and the IP address that sent
+ /// the data. null if this did not receive new IP data during the configured receive
+ /// timeout.
+ /// The IP address to read data from.
+ /// If == null.
+ /// If this device connection is not open.
+ ///
+ ///
+ public IPMessage ReadIPDataFrom(IPAddress ipAddress)
+ {
+ if (ipAddress == null)
+ throw new ArgumentNullException("IP address cannot be null.");
+
+ return ReadIPDataPacket(ipAddress, TIMEOUT_READ_PACKET);
+ }
+
+ ///
+ /// Reads new IP data received from the given IP address during the provided timeout.
+ ///
+ /// This method blocks until new IP data is received or the configured receive
+ /// timeout expires.
+ /// A object containing the IP data and the IP address that
+ /// sent the data. null if this did not receive new IP data during timeout
+ /// milliseconds.
+ /// The IP address to read data from.
+ /// The time to wait for new IP data in milliseconds.
+ /// If 0.
+ /// If == null.
+ /// If this device connection is not open.
+ ///
+ ///
+ public IPMessage ReadIPDataFrom(IPAddress ipAddress, int timeout)
+ {
+ if (ipAddress == null)
+ throw new ArgumentNullException("IP address cannot be null.");
+ if (timeout < 0)
+ throw new ArgumentException("Read timeout must be 0 or greater.");
+
+ return ReadIPDataPacket(ipAddress, timeout);
+ }
+
+ ///
+ /// Reads a new IP data packet received by this IP XBee device during the provided timeout.
+ ///
+ /// This method blocks until new IP data is received or the given timeout expires.
+ /// The IP address to get a IP data packet from. null to
+ /// read a IP data packet from any IP address.
+ /// The time to wait for a IP data packet in milliseconds.
+ /// A object containing the IP data and the IP address that
+ /// sent the data. null if this did not receive new IP data during timeout
+ /// milliseconds,or if any error occurs while trying to get the source of the message.
+ /// If this device connection is not open.
+ ///
+ ///
+ private IPMessage ReadIPDataPacket(IPAddress remoteIPAddress, int timeout)
+ {
+ // Check connection.
+ if (!ConnectionInterface.IsOpen)
+ throw new InterfaceNotOpenException();
+
+ XBeePacketsQueue xbeePacketsQueue = dataReader.XBeePacketsQueue;
+ XBeePacket xbeePacket = null;
+
+ if (remoteIPAddress != null)
+ xbeePacket = xbeePacketsQueue.GetFirstIPDataPacketFrom(remoteIPAddress, timeout);
+ else
+ xbeePacket = xbeePacketsQueue.GetFirstIPDataPacket(timeout);
+
+ if (xbeePacket == null)
+ return null;
+
+ // Obtain the data and IP address from the packet.
+ byte[] data = null;
+ IPAddress ipAddress = null;
+ int sourcePort;
+ int destPort;
+ IPProtocol protocol = IPProtocol.TCP;
+
+ switch ((xbeePacket as XBeeAPIPacket).FrameType)
+ {
+ case APIFrameType.RX_IPV4:
+ RXIPv4Packet receivePacket = (RXIPv4Packet)xbeePacket;
+ data = receivePacket.Data;
+ ipAddress = receivePacket.SourceAddress;
+ sourcePort = receivePacket.SourcePort;
+ destPort = receivePacket.DestPort;
+ break;
+ default:
+ return null;
+ }
+
+ // Create and return the IP message.
+ return new IPMessage(ipAddress, sourcePort, destPort, protocol, data);
+ }
+
+ ///
+ /// Sends the provided IP data to the given IP address and port using the specified IP protocol.
+ /// For TCP and TCP SSL protocols, you can also indicate if the socket should be closed when data
+ /// is sent.
+ ///
+ /// This method blocks till a success or error response arrives or the configured receive
+ /// timeout expires.
+ /// The IP address to send IP data to.
+ /// The destination port of the transmission.
+ /// The IP protocol used for the transmission.
+ /// true to close the socket just after the transmission. false
+ /// to keep it open.
+ /// Byte array containing the IP data to be sent.
+ /// If 0
+ /// or if ]]> 65535
+ /// or if == .
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote.
+ /// If there is a timeout sending the given packet synchronously.
+ /// If the transmit status generated when sending the
+ /// data is not an instance of
+ /// or if its transmit status is different from .
+ /// If there is any other XBee related error.
+ ///
+ ///
+ private void SendIPDataImpl(IPAddress ipAddress, int destPort,
+ IPProtocol protocol, bool closeSocket, byte[] data)
+ {
+ if (ipAddress == null)
+ throw new ArgumentNullException("IP address cannot be null");
+ if (protocol == IPProtocol.UNKNOWN)
+ throw new ArgumentException("Protocol cannot be unknown");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ if (destPort < 0 || destPort > 65535)
+ throw new ArgumentException("Destination port must be between 0 and 65535.");
+
+ // Check if device is remote.
+ if (IsRemote)
+ throw new InvalidOperationException("Cannot send IP data from a remote device.");
+
+ // The source port value depends on the protocol used in the transmission. For UDP, source port
+ // value must be the same as 'C0' one. For TCP it must be 0.
+ int sourcePort = protocol == IPProtocol.UDP ? this.sourcePort : 0;
+
+ logger.DebugFormat(ToString() + "Sending IP data to {}:{} >> {}.", ipAddress, destPort, HexUtils.PrettyHexString(data));
+ XBeePacket xbeePacket = new TXIPv4Packet(GetNextFrameID(), ipAddress, destPort,
+ sourcePort, protocol, closeSocket ? TXIPv4Packet.OPTIONS_CLOSE_SOCKET : TXIPv4Packet.OPTIONS_LEAVE_SOCKET_OPEN, data);
+
+ SendAndCheckXBeePacket(xbeePacket, false);
+ }
+
+ ///
+ /// Sends the provided IP data to the given IP address and port asynchronously using the specified IP
+ /// protocol. For TCP and TCP SSL protocols, you can also indicate if the socket should be closed when
+ /// data is sent.
+ ///
+ /// Asynchronous transmissions do not wait for answer from the remote device or for transmit
+ /// status packet.
+ /// The IP address to send IP data to.
+ /// The destination port of the transmission.
+ /// The IP protocol used for the transmission.
+ /// true to close the socket just after the transmission. false
+ /// to keep it open.
+ /// Byte array containing the IP data to be sent.
+ /// If 0
+ /// or if ]]> 65535
+ /// or if == .
+ /// If == null
+ /// or if == null.
+ /// If this device connection is not open.
+ /// If the device is remote.
+ /// If there is any other XBee related error.
+ ///
+ ///
+ private void SendIPDataAsyncImpl(IPAddress ipAddress, int destPort,
+ IPProtocol protocol, bool closeSocket, byte[] data)
+ {
+ if (ipAddress == null)
+ throw new ArgumentNullException("IP address cannot be null");
+ if (protocol == IPProtocol.UNKNOWN)
+ throw new ArgumentException("Protocol cannot be unknown");
+ if (data == null)
+ throw new ArgumentNullException("Data cannot be null");
+
+ if (destPort < 0 || destPort > 65535)
+ throw new ArgumentException("Destination port must be between 0 and 65535.");
+
+ // Check if device is remote.
+ if (IsRemote)
+ throw new InvalidOperationException("Cannot send IP data from a remote device.");
+
+ // The source port value depends on the protocol used in the transmission. For UDP, source port
+ // value must be the same as 'C0' one. For TCP it must be 0.
+ int sourcePort = protocol == IPProtocol.UDP ? this.sourcePort : 0;
+
+ logger.DebugFormat(ToString() + "Sending IP data asynchronously to {}:{} >> {}.", ipAddress, destPort, HexUtils.PrettyHexString(data));
+ XBeePacket xbeePacket = new TXIPv4Packet(GetNextFrameID(), ipAddress, destPort,
+ sourcePort, protocol, closeSocket ? TXIPv4Packet.OPTIONS_CLOSE_SOCKET : TXIPv4Packet.OPTIONS_LEAVE_SOCKET_OPEN, data);
+
+ SendAndCheckXBeePacket(xbeePacket, true);
+ }
+ }
+}
diff --git a/XBeeLibrary/LinkedDictionary.cs b/XBeeLibrary.Core/LinkedDictionary.cs
similarity index 74%
rename from XBeeLibrary/LinkedDictionary.cs
rename to XBeeLibrary.Core/LinkedDictionary.cs
index b91b848..f0c5f00 100644
--- a/XBeeLibrary/LinkedDictionary.cs
+++ b/XBeeLibrary.Core/LinkedDictionary.cs
@@ -1,186 +1,169 @@
-using System;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace System.Collections.Generic
-{
- public class LinkedDictionary : IDictionary/*, IList> where TKey : IEquatable*/
- {
- IList _keys = new List();
- IDictionary _datas = new Dictionary();
-
- struct Enumerator : IEnumerator>
- {
- LinkedDictionary _dictionary;
- IEnumerator _enumerator;
-
- internal Enumerator(LinkedDictionary dictionary, int getEnumeratorRetType)
- {
- _dictionary = dictionary;
- _enumerator = dictionary._keys.GetEnumerator();
- }
-
- public KeyValuePair Current
- {
- get { return new KeyValuePair(_enumerator.Current, _dictionary[_enumerator.Current]); }
- }
-
- public void Dispose()
- {
- _enumerator.Dispose();
- }
-
- object System.Collections.IEnumerator.Current
- {
- get { return Current; }
- }
-
- public bool MoveNext()
- {
- return _enumerator.MoveNext();
- }
-
- public void Reset()
- {
- _enumerator.Reset();
- }
- }
-
- #region IDictionary implementation
- public void Add(TKey key, TValue value)
- {
- if (_keys.Contains(key))
- _datas[key] = value;
- else
- {
- _keys.Add(key);
- _datas.Add(key, value);
- }
- }
-
- public bool ContainsKey(TKey key)
- {
- return _keys.Contains(key);
- }
-
- public ICollection Keys
- {
- get { return _datas.Keys; }
- }
-
- public bool Remove(TKey key)
- {
- _keys.Remove(key);
- return _datas.Remove(key);
- }
-
- public bool TryGetValue(TKey key, out TValue value)
- {
- return _datas.TryGetValue(key, out value);
- }
-
- public ICollection Values
- {
- get { return _datas.Values; }
- }
-
- public TValue this[TKey key]
- {
- get
- {
- return _datas[key];
- }
- set
- {
- _datas[key] = value;
- }
- }
-
- public void Add(KeyValuePair item)
- {
- if (_keys.Contains(item.Key))
- _datas[item.Key] = item.Value;
- else
- {
- _keys.Add(item.Key);
- _datas.Add(item);
- }
- }
-
- public void Clear()
- {
- _keys.Clear();
- _datas.Clear();
- }
-
- public bool Contains(KeyValuePair item)
- {
- return _datas.Contains(item);
- }
-
- public void CopyTo(KeyValuePair[] array, int arrayIndex)
- {
- foreach (var key in _keys)
- {
- array[arrayIndex++] = new KeyValuePair(key, _datas[key]);
- }
- }
-
- public int Count
- {
- get { return _keys.Count; }
- }
-
- public bool IsReadOnly
- {
- get { return false; }
- }
-
- public bool Remove(KeyValuePair item)
- {
- _keys.Remove(item.Key);
- return _datas.Remove(item);
- }
-
- public IEnumerator> GetEnumerator()
- {
- return new Enumerator(this, 0);
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- #endregion
-
- //#region IList> implementation
- //public int IndexOf(KeyValuePair item)
- //{
- // throw new NotImplementedException();
- //}
-
- //public void Insert(int index, KeyValuePair item)
- //{
- // throw new NotImplementedException();
- //}
-
- //public void RemoveAt(int index)
- //{
- // throw new NotImplementedException();
- //}
-
- //public KeyValuePair this[int index]
- //{
- // get
- // {
- // throw new NotImplementedException();
- // }
- // set
- // {
- // throw new NotImplementedException();
- // }
- //}
- //#endregion
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+namespace System.Collections.Generic
+{
+ public class LinkedDictionary : IDictionary
+ {
+ IList _keys = new List();
+ IDictionary _datas = new Dictionary();
+
+ struct Enumerator : IEnumerator>
+ {
+ LinkedDictionary _dictionary;
+ IEnumerator _enumerator;
+
+ internal Enumerator(LinkedDictionary dictionary, int getEnumeratorRetType)
+ {
+ _dictionary = dictionary;
+ _enumerator = dictionary._keys.GetEnumerator();
+ }
+
+ public KeyValuePair Current
+ {
+ get { return new KeyValuePair(_enumerator.Current, _dictionary[_enumerator.Current]); }
+ }
+
+ public void Dispose()
+ {
+ _enumerator.Dispose();
+ }
+
+ object System.Collections.IEnumerator.Current
+ {
+ get { return Current; }
+ }
+
+ public bool MoveNext()
+ {
+ return _enumerator.MoveNext();
+ }
+
+ public void Reset()
+ {
+ _enumerator.Reset();
+ }
+ }
+
+ #region IDictionary implementation
+ public void Add(TKey key, TValue value)
+ {
+ if (_keys.Contains(key))
+ _datas[key] = value;
+ else
+ {
+ _keys.Add(key);
+ _datas.Add(key, value);
+ }
+ }
+
+ public bool ContainsKey(TKey key)
+ {
+ return _keys.Contains(key);
+ }
+
+ public ICollection Keys
+ {
+ get { return _datas.Keys; }
+ }
+
+ public bool Remove(TKey key)
+ {
+ _keys.Remove(key);
+ return _datas.Remove(key);
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ return _datas.TryGetValue(key, out value);
+ }
+
+ public ICollection Values
+ {
+ get { return _datas.Values; }
+ }
+
+ public TValue this[TKey key]
+ {
+ get
+ {
+ return _datas[key];
+ }
+ set
+ {
+ _datas[key] = value;
+ }
+ }
+
+ public void Add(KeyValuePair item)
+ {
+ if (_keys.Contains(item.Key))
+ _datas[item.Key] = item.Value;
+ else
+ {
+ _keys.Add(item.Key);
+ _datas.Add(item);
+ }
+ }
+
+ public void Clear()
+ {
+ _keys.Clear();
+ _datas.Clear();
+ }
+
+ public bool Contains(KeyValuePair item)
+ {
+ return _datas.Contains(item);
+ }
+
+ public void CopyTo(KeyValuePair[] array, int arrayIndex)
+ {
+ foreach (var key in _keys)
+ {
+ array[arrayIndex++] = new KeyValuePair(key, _datas[key]);
+ }
+ }
+
+ public int Count
+ {
+ get { return _keys.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public bool Remove(KeyValuePair item)
+ {
+ _keys.Remove(item.Key);
+ return _datas.Remove(item);
+ }
+
+ public IEnumerator> GetEnumerator()
+ {
+ return new Enumerator(this, 0);
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ #endregion
+ }
+}
diff --git a/XBeeLibrary.Core/Models/APIOutputMode.cs b/XBeeLibrary.Core/Models/APIOutputMode.cs
new file mode 100644
index 0000000..3b6e006
--- /dev/null
+++ b/XBeeLibrary.Core/Models/APIOutputMode.cs
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different API output modes. The API output mode establishes
+ /// the way data will be output through the serial interface of an XBee device.
+ ///
+ public enum APIOutputMode : byte
+ {
+ // Enumeration entries.
+ MODE_NATIVE = 0x00,
+ MODE_EXPLICIT = 0x01,
+ MODE_EXPLICIT_ZDO_PASSTHRU = 0x03,
+ MODE_UNKNOWN = 0xFF
+ }
+
+ public static class APIOutputModeExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static APIOutputModeExtensions()
+ {
+ lookupTable.Add(APIOutputMode.MODE_NATIVE, "Native");
+ lookupTable.Add(APIOutputMode.MODE_EXPLICIT, "Explicit");
+ lookupTable.Add(APIOutputMode.MODE_EXPLICIT_ZDO_PASSTHRU, "Explicit with ZDO Passthru");
+ lookupTable.Add(APIOutputMode.MODE_UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Gets the API output mode value.
+ ///
+ ///
+ /// API output mode value.
+ public static byte GetValue(this APIOutputMode source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the API output mode description.
+ ///
+ ///
+ /// API output mode description.
+ public static string GetDescription(this APIOutputMode source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the associated with the specified ID .
+ ///
+ ///
+ /// ID value to retrieve .
+ /// The for the specified ID ,
+ /// if it does not exist.
+ public static APIOutputMode Get(this APIOutputMode source, byte value)
+ {
+ var values = Enum.GetValues(typeof(APIOutputMode)).OfType();
+
+ if (values.Cast().Contains(value))
+ return (APIOutputMode)value;
+
+ return APIOutputMode.MODE_UNKNOWN;
+ }
+
+ ///
+ /// Gets the string representation of the API output mode.
+ ///
+ ///
+ /// String representation of the API output mode.
+ public static string ToDisplayString(this APIOutputMode source)
+ {
+ return HexUtils.ByteToHexString((byte)source) + ": " + lookupTable[source];
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/ATCommand.cs b/XBeeLibrary.Core/Models/ATCommand.cs
new file mode 100644
index 0000000..218af05
--- /dev/null
+++ b/XBeeLibrary.Core/Models/ATCommand.cs
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Text;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an AT command used to read or set different properties of the XBee device.
+ ///
+ /// AT commands can be sent directly to the connected device or to remote devices and may
+ /// have parameters. After executing an AT Command, an AT Response is received from the device.
+ ///
+ ///
+ public class ATCommand
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The AT Command alias.
+ /// If is null.
+ /// If the Length of is
+ /// not 2.
+ public ATCommand(string command) : this(command, (byte[])null) { }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// If not is required, the constructor
+ /// is recommanded.
+ /// The AT Command alias.
+ /// The command parameter expressed as a string.
+ /// If is null.
+ /// If the Length of is not 2.
+ public ATCommand(string command, string parameter)
+ : this(command, parameter == null ? null : Encoding.UTF8.GetBytes(parameter)) { }
+
+ ///
+ /// Initializes a new instance of the class .
+ ///
+ /// If not is required, the constructor
+ /// is recommanded.
+ /// The AT Command alias.
+ /// The command parameter expressed as a byte array.
+ /// If is null.
+ /// If the Length of is not 2.
+ public ATCommand(string command, byte[] parameter)
+ {
+ if (command == null)
+ throw new ArgumentNullException("Command cannot be null.");
+ if (command.Length != 2)
+ throw new ArgumentException("Command lenght must be 2.");
+
+ Command = command;
+ Parameter = parameter;
+ }
+
+ // Properties.
+ ///
+ /// The AT command name.
+ ///
+ public string Command { get; private set; }
+
+ ///
+ /// The AT command parameter value.
+ ///
+ public byte[] Parameter { get; set; }
+
+ ///
+ /// The AT command parameter in string format.
+ ///
+ public string ParameterString
+ {
+ get
+ {
+ if (Parameter == null)
+ return null;
+
+ return Encoding.UTF8.GetString(Parameter, 0, Parameter.Length);
+ }
+ set
+ {
+ Parameter = Encoding.UTF8.GetBytes(value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary/Models/ATCommandResponse.cs b/XBeeLibrary.Core/Models/ATCommandResponse.cs
similarity index 56%
rename from XBeeLibrary/Models/ATCommandResponse.cs
rename to XBeeLibrary.Core/Models/ATCommandResponse.cs
index bd4b986..8323f63 100644
--- a/XBeeLibrary/Models/ATCommandResponse.cs
+++ b/XBeeLibrary.Core/Models/ATCommandResponse.cs
@@ -1,98 +1,106 @@
-using System;
-using System.Diagnostics.Contracts;
-using System.Text;
-
-namespace Kveer.XBeeApi.Models
-{
-
- ///
- /// This class represents the response of an AT Command sent by the connected XBee device or by a remote device after executing an AT Command.
- ///
- /// Among the executed command, this object contains the response data and the command status.
- ///
- ///
- public class ATCommandResponse
- {
- ///
- /// Gets the AT command that generated the response.
- ///
- ///
- public ATCommand Command { get; private set; }
-
- public ATCommandStatus Status { get; private set; }
-
- ///
- /// Gets the AT command response data in byte array format if any.
- ///
- public byte[] Response { get; private set; }
-
- ///
- /// Initializes a new instance of the class .
- ///
- /// The that generated the response.
- /// if is null or is null.
- ///
- public ATCommandResponse(ATCommand command)
- : this(command, null, ATCommandStatus.OK)
- {
- }
-
- ///
- /// Initializes a new instance of the class .
- ///
- /// The that generated the response.
- /// The containing the response status.
- /// if is null or is null.
- ///
- ///
- public ATCommandResponse(ATCommand command, ATCommandStatus status)
- : this(command, null, status)
- {
- }
-
- ///
- /// Initializes a new instance of the class .
- ///
- /// The that generated the response.
- /// The command response in byte array format.
- /// if is null or is null.
- ///
- public ATCommandResponse(ATCommand command, byte[] response)
- : this(command, response, ATCommandStatus.OK)
- {
- }
-
- ///
- /// Initializes a new instance of the class .
- ///
- /// The that generated the response.
- /// The command response in byte array format.
- /// The containing the response status.
- /// if is null or is null.
- ///
- ///
- public ATCommandResponse(ATCommand command, byte[] response, ATCommandStatus status)
- {
- Contract.Requires(command != null, "Command cannot be null.");
- Contract.Requires(status != null, "Status cannot be null.");
-
- Command = command;
- Response = response;
- Status = status;
- }
-
- ///
- /// Gest the AT command response data as string if any.
- ///
- public string ResponseString
- {
- get
- {
- if (Response == null)
- return null;
-
- return Encoding.UTF8.GetString(Response);
- }
- }
- }
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Text;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents the response of an AT Command sent by the connected XBee device or by a remote
+ /// device after executing an AT Command.
+ ///
+ /// Among the executed command, this object contains the response data and the command status.
+ ///
+ ///
+ public class ATCommandResponse
+ {
+ ///
+ /// Initializes a new instance of the class .
+ ///
+ /// The that generated the response.
+ /// If is null.
+ ///
+ public ATCommandResponse(ATCommand command) : this(command, null, ATCommandStatus.OK) { }
+
+ ///
+ /// Initializes a new instance of the class .
+ ///
+ /// The that generated the response.
+ /// The containing the response status.
+ /// If is null.
+ ///
+ ///
+ public ATCommandResponse(ATCommand command, ATCommandStatus status) : this(command, null, status) { }
+
+ ///
+ /// Initializes a new instance of the class .
+ ///
+ /// The that generated the response.
+ /// The command response in byte array format.
+ /// if is null.
+ ///
+ public ATCommandResponse(ATCommand command, byte[] response) : this(command, response, ATCommandStatus.OK) { }
+
+ ///
+ /// Initializes a new instance of the class .
+ ///
+ /// The that generated the response.
+ /// The command response in byte array format.
+ /// The containing the response status.
+ /// if is null.
+ ///
+ ///
+ public ATCommandResponse(ATCommand command, byte[] response, ATCommandStatus status)
+ {
+ Command = command ?? throw new ArgumentNullException("Command cannot be null.");
+ Response = response;
+ Status = status;
+ }
+
+ // Properties.
+ ///
+ /// The AT command that generated the response.
+ ///
+ ///
+ public ATCommand Command { get; private set; }
+
+ ///
+ /// The AT command status of the response.
+ ///
+ public ATCommandStatus Status { get; private set; }
+
+ ///
+ /// The AT command response data in byte array format, if any.
+ ///
+ public byte[] Response { get; private set; }
+
+ ///
+ /// The AT command response data as string, if any.
+ ///
+ public string ResponseString
+ {
+ get
+ {
+ if (Response == null)
+ return null;
+
+ return Encoding.UTF8.GetString(Response, 0, Response.Length);
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/XBeeLibrary/Models/ATCommandStatus.cs b/XBeeLibrary.Core/Models/ATCommandStatus.cs
similarity index 58%
rename from XBeeLibrary/Models/ATCommandStatus.cs
rename to XBeeLibrary.Core/Models/ATCommandStatus.cs
index 06280a0..4cfb4e0 100644
--- a/XBeeLibrary/Models/ATCommandStatus.cs
+++ b/XBeeLibrary.Core/Models/ATCommandStatus.cs
@@ -1,78 +1,101 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates all the possible states of an AT Command after executing it.
- /// objects will contain an entry of this enumerator indicating the status of the AT Command that was executed.
- ///
- ///
- public enum ATCommandStatus : byte
- {
- OK = 0,
- ERROR = 1,
- INVALID_COMMAND = 2,
- INVALID_PARAMETER = 3,
- TX_FAILURE = 4,
- UNKNOWN = 255
- }
-
- public static class ATCommandStatusExtensions
- {
- private static IDictionary lookupTable = new Dictionary();
-
- static ATCommandStatusExtensions()
- {
- lookupTable.Add(ATCommandStatus.OK, "Status OK");
- lookupTable.Add(ATCommandStatus.ERROR, "Status Error");
- lookupTable.Add(ATCommandStatus.INVALID_COMMAND, "Invalid command");
- lookupTable.Add(ATCommandStatus.INVALID_PARAMETER, "Invalid parameter");
- lookupTable.Add(ATCommandStatus.TX_FAILURE, "TX failure");
- lookupTable.Add(ATCommandStatus.UNKNOWN, "Unknown status");
- }
-
- ///
- /// Gets the AT Command Status ID.
- ///
- ///
- /// The AT Command Status ID.
- public static byte GetId(this ATCommandStatus source)
- {
- return (byte)source;
- }
-
- ///
- /// Gets the AT Command Status description
- ///
- ///
- /// The AT Command Status description.
- public static string GetDescription(this ATCommandStatus source)
- {
- return lookupTable[source];
- }
-
- ///
- /// Gest the associated to the specified .
- ///
- ///
- /// Id to retrieve the corresponding .
- /// The associated to the specified .
- public static ATCommandStatus Get(this ATCommandStatus dumb, byte id)
- {
- var values = Enum.GetValues(typeof(ATCommandStatus)).OfType();
-
- if (values.Cast().Contains(id))
- return (ATCommandStatus)id;
-
- return ATCommandStatus.UNKNOWN;
- }
-
-
- public static string ToDisplayString(this ATCommandStatus source)
- {
- return lookupTable[source];
- }
- }
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates all the possible states of an AT Command after executing it.
+ ///
+ /// The objects will contain an entry of this enumerator
+ /// indicating the status of the AT Command that was executed.
+ ///
+ public enum ATCommandStatus : byte
+ {
+ // Enumeration entries.
+ OK = 0,
+ ERROR = 1,
+ INVALID_COMMAND = 2,
+ INVALID_PARAMETER = 3,
+ TX_FAILURE = 4,
+ UNKNOWN = 255
+ }
+
+ public static class ATCommandStatusExtensions
+ {
+ private static IDictionary lookupTable = new Dictionary();
+
+ static ATCommandStatusExtensions()
+ {
+ lookupTable.Add(ATCommandStatus.OK, "Status OK");
+ lookupTable.Add(ATCommandStatus.ERROR, "Status Error");
+ lookupTable.Add(ATCommandStatus.INVALID_COMMAND, "Invalid command");
+ lookupTable.Add(ATCommandStatus.INVALID_PARAMETER, "Invalid parameter");
+ lookupTable.Add(ATCommandStatus.TX_FAILURE, "TX failure");
+ lookupTable.Add(ATCommandStatus.UNKNOWN, "Unknown status");
+ }
+
+ ///
+ /// Gets the AT Command Status ID.
+ ///
+ ///
+ /// The AT Command Status ID.
+ public static byte GetId(this ATCommandStatus source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the AT Command Status description.
+ ///
+ ///
+ /// The AT Command Status description.
+ public static string GetDescription(this ATCommandStatus source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gest the associated to the specified .
+ ///
+ ///
+ /// Id to retrieve the corresponding .
+ /// The associated to the specified .
+ public static ATCommandStatus Get(this ATCommandStatus source, byte id)
+ {
+ var values = Enum.GetValues(typeof(ATCommandStatus)).OfType();
+
+ if (values.Cast().Contains(id))
+ return (ATCommandStatus)id;
+
+ return ATCommandStatus.UNKNOWN;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this ATCommandStatus source)
+ {
+ return lookupTable[source];
+ }
+ }
}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/ATStringCommands.cs b/XBeeLibrary.Core/Models/ATStringCommands.cs
new file mode 100644
index 0000000..fc62fb5
--- /dev/null
+++ b/XBeeLibrary.Core/Models/ATStringCommands.cs
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates several AT commands used to parse AT command packets. The list of AT Command alias
+ /// listed here represents those AT commands whose values should be parsed as strings.
+ ///
+ public enum ATStringCommands
+ {
+ // Enumeration entries.
+ NI,
+ KY,
+ NK,
+ ZU,
+ ZV,
+ CC
+ }
+
+ public static class ATStringCommandsStructExtensions
+ {
+ ///
+ /// Gets the AT Command alias.
+ ///
+ ///
+ /// The AT Command alias.
+ public static string GetCommand(this ATStringCommands source)
+ {
+ return source.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/AbstractXBeeSetting.cs b/XBeeLibrary.Core/Models/AbstractXBeeSetting.cs
new file mode 100644
index 0000000..b68ea65
--- /dev/null
+++ b/XBeeLibrary.Core/Models/AbstractXBeeSetting.cs
@@ -0,0 +1,374 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class provides common functionality for all XBee settings.
+ ///
+ public abstract class AbstractXBeeSetting : ICloneable
+ {
+ // Constants.
+ public const int TYPE_NUMBER = 0;
+ public const int TYPE_COMBO = 1;
+ public const int TYPE_NO_CONTROL = 2;
+ public const int TYPE_TEXT = 3;
+ public const int TYPE_BUTTON = 4;
+
+ public const string COMMAND_BUFFER = "::";
+ public const string COMMAND_BUTTON = "()";
+
+ ///
+ /// Class constructor. Instantiates a new object with the
+ /// provided parameters.
+ ///
+ /// Name of the setting.
+ /// Description of the setting.
+ /// Default value of the setting.
+ /// Parent category of the setting.
+ /// XBee firmware the setting belongs to.
+ protected AbstractXBeeSetting(string name, string description, string defaultValue,
+ XBeeCategory parentCategory, XBeeFirmware ownerFirmware)
+ : this(null, name, description, defaultValue, parentCategory, ownerFirmware, 1) { }
+
+ ///
+ /// Class constructor. Instantiates a new object with the
+ /// provided parameters.
+ ///
+ /// Name of the setting.
+ /// Description of the setting.
+ /// Default value of the setting.
+ /// Parent category of the setting.
+ /// XBee firmware the setting belongs to.
+ /// The number of networks the setting can be configured for.
+ protected AbstractXBeeSetting(string name, string description, string defaultValue,
+ XBeeCategory parentCategory, XBeeFirmware ownerFirmware, int numNetworks)
+ : this(null, name, description, defaultValue, parentCategory, ownerFirmware, numNetworks) { }
+
+ ///
+ /// Class constructor. Instantiates a new object with the
+ /// provided parameters.
+ ///
+ /// The AT command corresponding to the setting.
+ /// Name of the setting.
+ /// Description of the setting.
+ /// Default value of the setting.
+ /// Parent category of the setting.
+ /// XBee firmware the setting belongs to.
+ protected AbstractXBeeSetting(string atCommand, string name, string description,
+ string defaultValue, XBeeCategory parentCategory, XBeeFirmware ownerFirmware)
+ : this(atCommand, name, description, defaultValue, parentCategory, ownerFirmware, 1) { }
+
+ ///
+ /// Class constructor. Instantiates a new object with the
+ /// provided parameters.
+ ///
+ /// The AT command corresponding to the setting.
+ /// Name of the setting.
+ /// Description of the setting.
+ /// Default value of the setting.
+ /// Parent category of the setting.
+ /// XBee firmware the setting belongs to.
+ /// The number of networks the setting can be configured for.
+ protected AbstractXBeeSetting(string atCommand, string name, string description, string defaultValue,
+ XBeeCategory parentCategory, XBeeFirmware ownerFirmware, int numNetworks)
+ {
+ AtCommand = atCommand;
+ Name = name;
+ Description = description;
+ DefaultValue = defaultValue;
+ ParentCategory = parentCategory;
+ OwnerFirmware = ownerFirmware;
+ NumNetworks = numNetworks;
+
+ // Fill values with default value.
+ for (int i = 0; i < numNetworks; i++)
+ CurrentValues.Add(defaultValue);
+
+ // Fill XBee values with default value.
+ for (int i = 0; i < numNetworks; i++)
+ XBeeValues.Add(defaultValue);
+ }
+
+ // Properties.
+ ///
+ /// AT command corresponding to the setting.
+ ///
+ public string AtCommand { get; set; }
+
+ ///
+ /// Name of the setting.
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Description of the setting.
+ ///
+ public string Description { get; set; }
+
+ ///
+ /// Default value of the setting.
+ ///
+ public string DefaultValue { get; set; }
+
+ ///
+ /// Number of networks the setting can be configured for.
+ ///
+ public int NumNetworks { get; set; }
+
+ ///
+ /// Type of setting.
+ ///
+ /// One of:
+ ///
+ /// - TYPE_NUMBER
+ /// - TYPE_COMBO
+ /// - TYPE_NO_CONTROL
+ /// - TYPE_TEXT
+ /// - TYPE_BUTTON
+ ///
+ public int Type { get; protected set; }
+
+ ///
+ /// Parent category of the setting.
+ ///
+ public XBeeCategory ParentCategory { get; set; }
+
+ ///
+ /// XBee firmware the setting belongs to.
+ ///
+ public XBeeFirmware OwnerFirmware { get; set; }
+
+ ///
+ /// Indicates whether the setting is enabled (can be edited) or not.
+ ///
+ public bool Enabled { get; set; } = true;
+
+ ///
+ /// Indicates whether the setting is visible or not.
+ ///
+ public bool Visible { get; set; } = true;
+
+ ///
+ /// Indicates whether the setting should be flashed as a custom default setting or not.
+ ///
+ public bool CustomDefault { get; set; } = false;
+
+ ///
+ /// Validation error message of the setting.
+ ///
+ public string ValidationErrorMessage { get; protected set; }
+
+ ///
+ /// List of current values, 1 for each network the setting can be configured for.
+ ///
+ public List CurrentValues { get; set; } = new List();
+
+ ///
+ /// List of XBee values (values stored in the XBee device), 1 for each network the setting
+ /// can be configured for.
+ ///
+ public List XBeeValues { get; set; } = new List();
+
+ ///
+ /// Returns whether or not the current value of the setting is valid.
+ ///
+ /// true if the value of the setting is valid, false
+ /// otherwise.
+ public abstract bool ValidateSetting();
+
+ ///
+ /// Returns whether or not the current value of the provided network index is valid.
+ ///
+ /// true if the value is valid, false otherwise.
+ public abstract bool ValidateSetting(int networkIndex);
+
+ ///
+ /// Returns the current value of the setting.
+ ///
+ /// The current value of the setting.
+ public string GetCurrentValue()
+ {
+ return CurrentValues[0];
+ }
+
+ ///
+ /// Returns the current value of the setting for the given network index.
+ ///
+ /// Network index to retrieve the setting value from. Index starts at 1.
+ /// The current value of the setting for the given network index.
+ public string GetCurrentValue(int networkIndex)
+ {
+ if (networkIndex == 0)
+ networkIndex = 1;
+
+ if (networkIndex > NumNetworks)
+ return CurrentValues[0];
+
+ return CurrentValues[networkIndex - 1];
+ }
+
+ ///
+ /// Sets the current value of the setting.
+ ///
+ /// The current value to set to the setting.
+ public void SetCurrentValue(string currentValue)
+ {
+ CurrentValues[0] = currentValue;
+ CustomDefault = false;
+ }
+
+ ///
+ /// Sets the current value of the setting for the given network index.
+ ///
+ /// The current value for the given network index.
+ /// Index of the network this value is for. Index starts
+ /// at 1.
+ public void SetCurrentValue(string currentValue, int networkIndex)
+ {
+ if (networkIndex == 0)
+ networkIndex = 1;
+
+ if (networkIndex > NumNetworks)
+ CurrentValues[0] = currentValue;
+ else
+ CurrentValues[networkIndex - 1] = currentValue;
+
+ CustomDefault = false;
+ }
+
+ ///
+ /// Returns the value of the setting that is stored in the XBee device.
+ ///
+ /// The XBee setting value.
+ public string GetXBeeValue()
+ {
+ return XBeeValues[0];
+ }
+
+ ///
+ /// Returns the current value of the setting that is stored in the XBee device for the given network index.
+ ///
+ /// Network index to retrieve the setting value from. Index starts at 1.
+ /// The XBee setting value for the given network index.
+ public string GetXBeeValue(int networkIndex)
+ {
+ if (networkIndex == 0)
+ networkIndex = 1;
+
+ if (networkIndex > NumNetworks)
+ return XBeeValues[0];
+
+ return XBeeValues[networkIndex - 1];
+ }
+
+ ///
+ /// Sets the value of the setting that is stored in the XBee device.
+ ///
+ /// The XBee setting value to set to the setting.
+ public void SetXBeeValue(string xbeeValue)
+ {
+ XBeeValues[0] = xbeeValue;
+ }
+
+ ///
+ /// Sets the value of the setting that is stored in the XBee device for the given network index.
+ ///
+ /// The XBee setting value for the given network index.
+ /// Index of the network this value is for. Index starts at 1.
+ public void SetXBeeValue(string xbeeValue, int networkIndex)
+ {
+ if (networkIndex == 0)
+ networkIndex = 1;
+
+ if (networkIndex > NumNetworks)
+ XBeeValues[0] = xbeeValue;
+ else
+ XBeeValues[networkIndex - 1] = xbeeValue;
+ }
+
+ ///
+ /// Returns whether this setting addresses multiple networks or not.
+ ///
+ /// true if the setting addresses more than 1 network, false
+ /// otherwise.
+ public bool SupportsMultipleNetworks()
+ {
+ return NumNetworks > 1;
+ }
+
+ ///
+ /// Returns the setting label to be displayed in the configuration editor.
+ ///
+ /// The label for the setting.
+ public string GetLabel()
+ {
+ string label = "";
+ if (AtCommand != null)
+ label = "[" + AtCommand + "]";
+ else
+ label = Name;
+
+ return label;
+ }
+
+ ///
+ /// Returns the string representation (name) of the setting.
+ ///
+ /// The string representation (name) of the setting.
+ public string Tostring()
+ {
+ return Name;
+ }
+
+ ///
+ /// Creates a shallow copy of the AbstractXBeeSetting.
+ ///
+ /// The copy of the AbstractXBeeSetting
+ public object Clone()
+ {
+ return MemberwiseClone() as AbstractXBeeSetting;
+ }
+
+ ///
+ /// Clones and returns the setting object.
+ ///
+ /// The parent category where the cloned setting should be placed.
+ /// The owner firmware of the cloned setting.
+ /// The cloned setting object.
+ public AbstractXBeeSetting CloneSetting(XBeeCategory parentCategory, XBeeFirmware ownerFirmware)
+ {
+ AbstractXBeeSetting clonedSetting = (AbstractXBeeSetting)Clone();
+ clonedSetting.ParentCategory = parentCategory;
+ clonedSetting.OwnerFirmware = ownerFirmware;
+
+ // Clone the list of current values.
+ List clonedCurrentValues = new List();
+ clonedCurrentValues.AddRange(CurrentValues);
+ clonedSetting.CurrentValues = clonedCurrentValues;
+
+ // Clone the list of XBee values.
+ List clonedXBeeValues = new List();
+ clonedXBeeValues.AddRange(XBeeValues);
+ clonedSetting.XBeeValues = clonedXBeeValues;
+
+ return clonedSetting;
+ }
+ }
+}
diff --git a/XBeeLibrary/Models/AssociationIndicationStatus.cs b/XBeeLibrary.Core/Models/AssociationIndicationStatus.cs
similarity index 80%
rename from XBeeLibrary/Models/AssociationIndicationStatus.cs
rename to XBeeLibrary.Core/Models/AssociationIndicationStatus.cs
index 1697b26..8b21c06 100644
--- a/XBeeLibrary/Models/AssociationIndicationStatus.cs
+++ b/XBeeLibrary.Core/Models/AssociationIndicationStatus.cs
@@ -1,125 +1,150 @@
-using Kveer.XBeeApi.Utils;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates the different association indication status.
- ///
- public enum AssociationIndicationStatus : byte
- {
- SUCCESSFULLY_JOINED = 0x00,
- AS_TIMEOUT = 0x01,
- AS_NO_PANS_FOUND = 0x02,
- AS_ASSOCIATION_NOT_ALLOED = 0x03,
- AS_BEACONS_NOT_SUPPORTED = 0x04,
- AS_ID_DOESNT_MATCH = 0x05,
- AS_CHANNEL_DOESNT_MATCH = 0x06,
- ENERGY_SCAN_TIMEOUT = 0x07,
- COORDINATOR_START_REQUEST_FAILED = 0x08,
- COORDINATOR_INVALID_PARAMETER = 0x09,
- COORDINATOR_REALIGNMENT = 0x0A,
- AR_NOT_SENT = 0x0B,
- AR_TIMED_OUT = 0x0C,
- AR_INVALID_PARAMETER = 0x0D,
- AR_CHANNEL_ACCESS_FAILURE = 0x0E,
- AR_COORDINATOT_ACK_WASNT_RECEIVED = 0x0F,
- AR_COORDINATOT_DIDNT_REPLY = 0x10,
- SYNCHRONIZATION_LOST = 0x12,
- DISSASOCIATED = 0x13,
- NO_PANS_FOUND = 0x21,
- NO_PANS_WITH_ID_FOUND = 0x22,
- NJ_EXPIRED = 0x23,
- NO_JOINABLE_BEACONS_FOUND = 0x24,
- UNEXPECTED_STATE = 0x25,
- JOIN_FAILED = 0x27,
- COORDINATOR_START_FAILED = 0x2A,
- CHECKING_FOR_COORDINATOR = 0x2B,
- NETWORK_LEAVE_FAILED = 0x2C,
- DEVICE_DIDNT_RESPOND = 0xAB,
- UNSECURED_KEY_RECEIVED = 0xAC,
- KEY_NOT_RECEIVED = 0xAD,
- INVALID_SECURITY_KEY = 0xAF,
- SCANNING_NETWORK = 0xff
- }
-
- public static class AssociationIndicationStatusExtensions
- {
- private static IDictionary lookupTable = new Dictionary();
-
- static AssociationIndicationStatusExtensions()
- {
- lookupTable.Add(AssociationIndicationStatus.SUCCESSFULLY_JOINED, "Successfully formed or joined a network.");
- lookupTable.Add(AssociationIndicationStatus.AS_TIMEOUT, "Active Scan Timeout.");
- lookupTable.Add(AssociationIndicationStatus.AS_NO_PANS_FOUND, "Active Scan found no PANs.");
- lookupTable.Add(AssociationIndicationStatus.AS_ASSOCIATION_NOT_ALLOED, "Active Scan found PAN, but the CoordinatorAllowAssociation bit is not set.");
- lookupTable.Add(AssociationIndicationStatus.AS_BEACONS_NOT_SUPPORTED, "Active Scan found PAN, but Coordinator and End Device are not configured to support beacons.");
- lookupTable.Add(AssociationIndicationStatus.AS_ID_DOESNT_MATCH, "Active Scan found PAN, but the Coordinator ID parameter does not match the ID parameter of the End Device.");
- lookupTable.Add(AssociationIndicationStatus.AS_CHANNEL_DOESNT_MATCH, "Active Scan found PAN, but the Coordinator CH parameter does not match the CH parameter of the End Device.");
- lookupTable.Add(AssociationIndicationStatus.ENERGY_SCAN_TIMEOUT, "Energy Scan Timeout.");
- lookupTable.Add(AssociationIndicationStatus.COORDINATOR_START_REQUEST_FAILED, "Coordinator start request failed.");
- lookupTable.Add(AssociationIndicationStatus.COORDINATOR_INVALID_PARAMETER, "Coordinator could not start due to invalid parameter.");
- lookupTable.Add(AssociationIndicationStatus.COORDINATOR_REALIGNMENT, "Coordinator Realignment is in progress.");
- lookupTable.Add(AssociationIndicationStatus.AR_NOT_SENT, "Association Request not sent.");
- lookupTable.Add(AssociationIndicationStatus.AR_TIMED_OUT, "Association Request timed out - no reply was received.");
- lookupTable.Add(AssociationIndicationStatus.AR_INVALID_PARAMETER, "Association Request had an Invalid Parameter.");
- lookupTable.Add(AssociationIndicationStatus.AR_CHANNEL_ACCESS_FAILURE, "Association Request Channel Access Failure. Request was not transmitted - CCA failure.");
- lookupTable.Add(AssociationIndicationStatus.AR_COORDINATOT_ACK_WASNT_RECEIVED, "Remote Coordinator did not send an ACK after Association Request was sent.");
- lookupTable.Add(AssociationIndicationStatus.AR_COORDINATOT_DIDNT_REPLY, "Remote Coordinator did not reply to the Association Request, but an ACK was received after sending the request.");
- lookupTable.Add(AssociationIndicationStatus.SYNCHRONIZATION_LOST, "Sync-Loss - Lost synchronization with a Beaconing Coordinator.");
- lookupTable.Add(AssociationIndicationStatus.DISSASOCIATED, "Disassociated - No longer associated to Coordinator.");
- lookupTable.Add(AssociationIndicationStatus.NO_PANS_FOUND, "Scan found no PANs.");
- lookupTable.Add(AssociationIndicationStatus.NO_PANS_WITH_ID_FOUND, "Scan found no valid PANs based on current SC and ID settings.");
- lookupTable.Add(AssociationIndicationStatus.NJ_EXPIRED, "Valid Coordinator or Routers found, but they are not allowing joining (NJ expired).");
- lookupTable.Add(AssociationIndicationStatus.NO_JOINABLE_BEACONS_FOUND, "No joinable beacons were found.");
- lookupTable.Add(AssociationIndicationStatus.UNEXPECTED_STATE, "Unexpected state, node should not be attempting to join at this time.");
- lookupTable.Add(AssociationIndicationStatus.JOIN_FAILED, "Node Joining attempt failed (typically due to incompatible security settings).");
- lookupTable.Add(AssociationIndicationStatus.COORDINATOR_START_FAILED, "Coordinator Start attempt failed.");
- lookupTable.Add(AssociationIndicationStatus.CHECKING_FOR_COORDINATOR, "Checking for an existing coordinator.");
- lookupTable.Add(AssociationIndicationStatus.NETWORK_LEAVE_FAILED, "Attempt to leave the network failed.");
- lookupTable.Add(AssociationIndicationStatus.DEVICE_DIDNT_RESPOND, "Attempted to join a device that did not respond.");
- lookupTable.Add(AssociationIndicationStatus.UNSECURED_KEY_RECEIVED, "Secure join error - network security key received unsecured.");
- lookupTable.Add(AssociationIndicationStatus.KEY_NOT_RECEIVED, "Secure join error - network security key not received.");
- lookupTable.Add(AssociationIndicationStatus.INVALID_SECURITY_KEY, "Secure join error - joining device does not have the right preconfigured link key.");
- lookupTable.Add(AssociationIndicationStatus.SCANNING_NETWORK, "Scanning for a network/Attempting to associate.");
- }
-
- ///
- /// Gets the association indication status value.
- ///
- ///
- /// The association indication status value.
- public static byte GetValue(this AssociationIndicationStatus source)
- {
- return (byte)source;
- }
-
- ///
- /// Gets the association indication status description.
- ///
- ///
- /// The association indication status description.
- public static string GetDescription(this AssociationIndicationStatus source)
- {
- return lookupTable[source];
- }
-
- public static AssociationIndicationStatus Get(this AssociationIndicationStatus dumb, byte value)
- {
- //var values = Enum.GetValues(typeof(AssociationIndicationStatus));
- //if (values.OfType().Contains(value))
- return (AssociationIndicationStatus)value;
- }
-
- public static string ToDisplayString(this AssociationIndicationStatus source)
- {
- var data = lookupTable[source];
-
- return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source), data);
- }
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System.Collections.Generic;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different association indication status.
+ ///
+ public enum AssociationIndicationStatus : byte
+ {
+ // Enumeration entries.
+ SUCCESSFULLY_JOINED = 0x00,
+ AS_TIMEOUT = 0x01,
+ AS_NO_PANS_FOUND = 0x02,
+ AS_ASSOCIATION_NOT_ALLOED = 0x03,
+ AS_BEACONS_NOT_SUPPORTED = 0x04,
+ AS_ID_DOESNT_MATCH = 0x05,
+ AS_CHANNEL_DOESNT_MATCH = 0x06,
+ ENERGY_SCAN_TIMEOUT = 0x07,
+ COORDINATOR_START_REQUEST_FAILED = 0x08,
+ COORDINATOR_INVALID_PARAMETER = 0x09,
+ COORDINATOR_REALIGNMENT = 0x0A,
+ AR_NOT_SENT = 0x0B,
+ AR_TIMED_OUT = 0x0C,
+ AR_INVALID_PARAMETER = 0x0D,
+ AR_CHANNEL_ACCESS_FAILURE = 0x0E,
+ AR_COORDINATOT_ACK_WASNT_RECEIVED = 0x0F,
+ AR_COORDINATOT_DIDNT_REPLY = 0x10,
+ SYNCHRONIZATION_LOST = 0x12,
+ DISSASOCIATED = 0x13,
+ NO_PANS_FOUND = 0x21,
+ NO_PANS_WITH_ID_FOUND = 0x22,
+ NJ_EXPIRED = 0x23,
+ NO_JOINABLE_BEACONS_FOUND = 0x24,
+ UNEXPECTED_STATE = 0x25,
+ JOIN_FAILED = 0x27,
+ COORDINATOR_START_FAILED = 0x2A,
+ CHECKING_FOR_COORDINATOR = 0x2B,
+ NETWORK_LEAVE_FAILED = 0x2C,
+ DEVICE_DIDNT_RESPOND = 0xAB,
+ UNSECURED_KEY_RECEIVED = 0xAC,
+ KEY_NOT_RECEIVED = 0xAD,
+ INVALID_SECURITY_KEY = 0xAF,
+ SCANNING_NETWORK = 0xff
+ }
+
+ public static class AssociationIndicationStatusExtensions
+ {
+ private static IDictionary lookupTable = new Dictionary();
+
+ static AssociationIndicationStatusExtensions()
+ {
+ lookupTable.Add(AssociationIndicationStatus.SUCCESSFULLY_JOINED, "Successfully formed or joined a network.");
+ lookupTable.Add(AssociationIndicationStatus.AS_TIMEOUT, "Active Scan Timeout.");
+ lookupTable.Add(AssociationIndicationStatus.AS_NO_PANS_FOUND, "Active Scan found no PANs.");
+ lookupTable.Add(AssociationIndicationStatus.AS_ASSOCIATION_NOT_ALLOED, "Active Scan found PAN, but the CoordinatorAllowAssociation bit is not set.");
+ lookupTable.Add(AssociationIndicationStatus.AS_BEACONS_NOT_SUPPORTED, "Active Scan found PAN, but Coordinator and End Device are not configured to support beacons.");
+ lookupTable.Add(AssociationIndicationStatus.AS_ID_DOESNT_MATCH, "Active Scan found PAN, but the Coordinator ID parameter does not match the ID parameter of the End Device.");
+ lookupTable.Add(AssociationIndicationStatus.AS_CHANNEL_DOESNT_MATCH, "Active Scan found PAN, but the Coordinator CH parameter does not match the CH parameter of the End Device.");
+ lookupTable.Add(AssociationIndicationStatus.ENERGY_SCAN_TIMEOUT, "Energy Scan Timeout.");
+ lookupTable.Add(AssociationIndicationStatus.COORDINATOR_START_REQUEST_FAILED, "Coordinator start request failed.");
+ lookupTable.Add(AssociationIndicationStatus.COORDINATOR_INVALID_PARAMETER, "Coordinator could not start due to invalid parameter.");
+ lookupTable.Add(AssociationIndicationStatus.COORDINATOR_REALIGNMENT, "Coordinator Realignment is in progress.");
+ lookupTable.Add(AssociationIndicationStatus.AR_NOT_SENT, "Association Request not sent.");
+ lookupTable.Add(AssociationIndicationStatus.AR_TIMED_OUT, "Association Request timed out - no reply was received.");
+ lookupTable.Add(AssociationIndicationStatus.AR_INVALID_PARAMETER, "Association Request had an Invalid Parameter.");
+ lookupTable.Add(AssociationIndicationStatus.AR_CHANNEL_ACCESS_FAILURE, "Association Request Channel Access Failure. Request was not transmitted - CCA failure.");
+ lookupTable.Add(AssociationIndicationStatus.AR_COORDINATOT_ACK_WASNT_RECEIVED, "Remote Coordinator did not send an ACK after Association Request was sent.");
+ lookupTable.Add(AssociationIndicationStatus.AR_COORDINATOT_DIDNT_REPLY, "Remote Coordinator did not reply to the Association Request, but an ACK was received after sending the request.");
+ lookupTable.Add(AssociationIndicationStatus.SYNCHRONIZATION_LOST, "Sync-Loss - Lost synchronization with a Beaconing Coordinator.");
+ lookupTable.Add(AssociationIndicationStatus.DISSASOCIATED, "Disassociated - No longer associated to Coordinator.");
+ lookupTable.Add(AssociationIndicationStatus.NO_PANS_FOUND, "Scan found no PANs.");
+ lookupTable.Add(AssociationIndicationStatus.NO_PANS_WITH_ID_FOUND, "Scan found no valid PANs based on current SC and ID settings.");
+ lookupTable.Add(AssociationIndicationStatus.NJ_EXPIRED, "Valid Coordinator or Routers found, but they are not allowing joining (NJ expired).");
+ lookupTable.Add(AssociationIndicationStatus.NO_JOINABLE_BEACONS_FOUND, "No joinable beacons were found.");
+ lookupTable.Add(AssociationIndicationStatus.UNEXPECTED_STATE, "Unexpected state, node should not be attempting to join at this time.");
+ lookupTable.Add(AssociationIndicationStatus.JOIN_FAILED, "Node Joining attempt failed (typically due to incompatible security settings).");
+ lookupTable.Add(AssociationIndicationStatus.COORDINATOR_START_FAILED, "Coordinator Start attempt failed.");
+ lookupTable.Add(AssociationIndicationStatus.CHECKING_FOR_COORDINATOR, "Checking for an existing coordinator.");
+ lookupTable.Add(AssociationIndicationStatus.NETWORK_LEAVE_FAILED, "Attempt to leave the network failed.");
+ lookupTable.Add(AssociationIndicationStatus.DEVICE_DIDNT_RESPOND, "Attempted to join a device that did not respond.");
+ lookupTable.Add(AssociationIndicationStatus.UNSECURED_KEY_RECEIVED, "Secure join error - network security key received unsecured.");
+ lookupTable.Add(AssociationIndicationStatus.KEY_NOT_RECEIVED, "Secure join error - network security key not received.");
+ lookupTable.Add(AssociationIndicationStatus.INVALID_SECURITY_KEY, "Secure join error - joining device does not have the right preconfigured link key.");
+ lookupTable.Add(AssociationIndicationStatus.SCANNING_NETWORK, "Scanning for a network/Attempting to associate.");
+ }
+
+ ///
+ /// Gets the association indication status value.
+ ///
+ ///
+ /// The association indication status value.
+ public static byte GetValue(this AssociationIndicationStatus source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the association indication status description.
+ ///
+ ///
+ /// The association indication status description.
+ public static string GetDescription(this AssociationIndicationStatus source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the associated with the specified
+ /// .
+ ///
+ ///
+ /// The value to retrieve the associated
+ /// for.
+ /// The associated with the specified
+ /// .
+ public static AssociationIndicationStatus Get(this AssociationIndicationStatus source, byte value)
+ {
+ return (AssociationIndicationStatus)value;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this AssociationIndicationStatus source)
+ {
+ var data = lookupTable[source];
+
+ return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source), data);
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/CellularAssociationIndicationStatus.cs b/XBeeLibrary.Core/Models/CellularAssociationIndicationStatus.cs
new file mode 100644
index 0000000..7911005
--- /dev/null
+++ b/XBeeLibrary.Core/Models/CellularAssociationIndicationStatus.cs
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different association indication statuses for the Cellular
+ /// protocol.
+ ///
+ public enum CellularAssociationIndicationStatus
+ {
+ // Enumeration entries.
+ SUCCESSFULLY_CONNECTED = 0x00,
+ POWERED_UP = 0x20,
+ IDENTIFIED = 0x21,
+ REGISTERING = 0x22,
+ REGISTERED = 0x23,
+ SETUP_DEVICE = 0xA0,
+ SETUP_USB = 0xC0,
+ POWERUP = 0xE0,
+ UNKNOWN = 0xFA,
+ REBOOTING = 0xFB,
+ SHUTTING_DOWN = 0xFC,
+ MANUFACTURING_STATE = 0xFD,
+ UNEXPECTED_STATE = 0xFE,
+ POWERED_DOWN = 0xFF
+ }
+
+ public static class CellularAssociationIndicationStatusExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static CellularAssociationIndicationStatusExtensions()
+ {
+ lookupTable.Add(CellularAssociationIndicationStatus.SUCCESSFULLY_CONNECTED, "Connected to the Internet.");
+ lookupTable.Add(CellularAssociationIndicationStatus.POWERED_UP, "Modem powered up and enumerated.");
+ lookupTable.Add(CellularAssociationIndicationStatus.IDENTIFIED, "Modem identified.");
+ lookupTable.Add(CellularAssociationIndicationStatus.REGISTERING, "Modem registering.");
+ lookupTable.Add(CellularAssociationIndicationStatus.REGISTERED, "Modem registered.");
+ lookupTable.Add(CellularAssociationIndicationStatus.SETUP_DEVICE, "Setup modem device.");
+ lookupTable.Add(CellularAssociationIndicationStatus.SETUP_USB, "Setup modem USB.");
+ lookupTable.Add(CellularAssociationIndicationStatus.POWERUP, "Power up modem.");
+ lookupTable.Add(CellularAssociationIndicationStatus.UNKNOWN, "Status unknown.");
+ lookupTable.Add(CellularAssociationIndicationStatus.REBOOTING, "Rebooting modem.");
+ lookupTable.Add(CellularAssociationIndicationStatus.SHUTTING_DOWN, "Shutting down modem.");
+ lookupTable.Add(CellularAssociationIndicationStatus.MANUFACTURING_STATE, "Modem in manufacturing state.");
+ lookupTable.Add(CellularAssociationIndicationStatus.UNEXPECTED_STATE, "Modem in unexpected state.");
+ lookupTable.Add(CellularAssociationIndicationStatus.POWERED_DOWN, "Modem powered down.");
+ }
+
+ ///
+ /// Gets the status ID.
+ ///
+ ///
+ /// Status ID.
+ public static int GetId(this CellularAssociationIndicationStatus source)
+ {
+ return (int)source;
+ }
+
+ ///
+ /// Gets the status description.
+ ///
+ ///
+ /// Status description.
+ public static string GetDescription(this CellularAssociationIndicationStatus source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the associated to the given ID.
+ ///
+ ///
+ /// ID of the to retrieve.
+ /// The associated with the given ID.
+ public static CellularAssociationIndicationStatus Get(this CellularAssociationIndicationStatus source, int id)
+ {
+ var values = Enum.GetValues(typeof(CellularAssociationIndicationStatus));
+
+ if (values.OfType().Contains(id))
+ return (CellularAssociationIndicationStatus)id;
+
+ return CellularAssociationIndicationStatus.UNKNOWN;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this CellularAssociationIndicationStatus source)
+ {
+ return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)(int)source), source.GetDescription());
+ }
+ }
+}
diff --git a/XBeeLibrary/Models/DiscoveryOptions.cs b/XBeeLibrary.Core/Models/DiscoveryOptions.cs
similarity index 61%
rename from XBeeLibrary/Models/DiscoveryOptions.cs
rename to XBeeLibrary.Core/Models/DiscoveryOptions.cs
index 8c97b3b..d7c3734 100644
--- a/XBeeLibrary/Models/DiscoveryOptions.cs
+++ b/XBeeLibrary.Core/Models/DiscoveryOptions.cs
@@ -1,119 +1,149 @@
-using System.Collections.Generic;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates the different options used in the discovery process.
- ///
- public enum DiscoveryOptions : byte
- {
- ///
- /// Append device type identifier (DD) to the discovery response.
- ///
- /// Valid for the following protocols:
- /// DigiMesh
- /// Point-to-multipoint (Digi Point)
- /// ZigBee
- ///
- APPEND_DD = 1,
-
- ///
- /// Local device sends response frame when discovery is issued.
- ///
- /// Valid for the following protocols:
- /// DigiMesh
- /// Point-to-multipoint (Digi Point)
- /// ZigBee
- /// 802.15.4
- ///
- DISCOVER_MYSELF = 2,
-
- ///
- /// Append RSSI of the last hop to the discovery response.
- ///
- /// Valid for the following protocols:
- /// DigiMesh
- /// Point-to-multipoint (Digi Point)
- ///
- APPEND_RSSI = 4
- }
-
- public static class DiscoveryOptionsExtensions
- {
- static IDictionary lookupTable = new Dictionary();
-
- static DiscoveryOptionsExtensions()
- {
- lookupTable.Add(DiscoveryOptions.APPEND_DD, "Append device type identifier (DD)");
- lookupTable.Add(DiscoveryOptions.DISCOVER_MYSELF, "Local device sends response frame");
- lookupTable.Add(DiscoveryOptions.APPEND_RSSI, "Append RSSI (of the last hop)");
- }
-
- ///
- /// Gets the value of the discovery option.
- ///
- ///
- /// The value of the discovery option.
- public static int GetValue(this DiscoveryOptions source)
- {
- return (int)source;
- }
-
- ///
- /// Gets the description of the discovery option.
- ///
- ///
- /// The discovery option description.
- public static string GetDescription(this DiscoveryOptions source)
- {
- return lookupTable[source];
- }
-
- ///
- /// Calculates the total value of a combination of several options for the given protocol.
- ///
- /// The to calculate the value of all the given discovery options.
- /// Collection of options to get the final value.
- /// The value to be configured in the module depending on the given collection of options and the protocol.
- public static int CalculateDiscoveryValue(this DiscoveryOptions dumb, XBeeProtocol protocol, ISet options)
- {
- // Calculate value to be configured.
- int value = 0;
- switch (protocol)
- {
- case XBeeProtocol.ZIGBEE:
- case XBeeProtocol.ZNET:
- foreach (DiscoveryOptions op in options)
- {
- if (op == DiscoveryOptions.APPEND_RSSI)
- continue;
- value = value + op.GetValue();
- }
- break;
- case XBeeProtocol.DIGI_MESH:
- case XBeeProtocol.DIGI_POINT:
- case XBeeProtocol.XLR:
- // TODO [XLR_DM] The next version of the XLR will add DigiMesh support.
- // For the moment only point-to-multipoint is supported in this kind of devices.
- case XBeeProtocol.XLR_DM:
- foreach (DiscoveryOptions op in options)
- value = value + op.GetValue();
- break;
- case XBeeProtocol.RAW_802_15_4:
- case XBeeProtocol.UNKNOWN:
- default:
- if (options.Contains(DiscoveryOptions.DISCOVER_MYSELF))
- value = 1; // This is different for 802.15.4.
- break;
- }
- return value;
- }
-
- public static string ToDisplayString(this DiscoveryOptions source)
- {
- var value = lookupTable[source];
-
- return string.Format("{0} ({1})", value, (byte)source);
- }
- }
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System.Collections.Generic;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different options used in the discovery process.
+ ///
+ public enum DiscoveryOptions : byte
+ {
+ // Enumeration entries.
+ ///
+ /// Append device type identifier (DD) to the discovery response.
+ ///
+ /// Valid for the following protocols:
+ ///
+ /// - DigiMesh
+ /// - Point-to-multipoint (Digi Point)
+ /// - ZigBee
+ ///
+ APPEND_DD = 1,
+
+ ///
+ /// Local device sends response frame when discovery is issued.
+ ///
+ /// Valid for the following protocols:
+ ///
+ /// - DigiMesh
+ /// - Point-to-multipoint (Digi Point)
+ /// - ZigBee
+ /// - 802.15.4
+ ///
+ DISCOVER_MYSELF = 2,
+
+ ///
+ /// Append RSSI of the last hop to the discovery response.
+ ///
+ /// Valid for the following protocols:
+ ///
+ /// - DigiMesh
+ /// - Point-to-multipoint (Digi Point)
+ ///
+ APPEND_RSSI = 4
+ }
+
+ public static class DiscoveryOptionsExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static DiscoveryOptionsExtensions()
+ {
+ lookupTable.Add(DiscoveryOptions.APPEND_DD, "Append device type identifier (DD)");
+ lookupTable.Add(DiscoveryOptions.DISCOVER_MYSELF, "Local device sends response frame");
+ lookupTable.Add(DiscoveryOptions.APPEND_RSSI, "Append RSSI (of the last hop)");
+ }
+
+ ///
+ /// Gets the value of the discovery option.
+ ///
+ ///
+ /// The value of the discovery option.
+ public static int GetValue(this DiscoveryOptions source)
+ {
+ return (int)source;
+ }
+
+ ///
+ /// Gets the description of the discovery option.
+ ///
+ ///
+ /// The discovery option description.
+ public static string GetDescription(this DiscoveryOptions source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Calculates the total value of a combination of several options for the given protocol.
+ ///
+ ///
+ /// The to calculate the value of all the given
+ /// discovery options.
+ /// Collection of options to get the final value.
+ /// The value to be configured in the module depending on the given collection of options
+ /// and the protocol.
+ ///
+ public static int CalculateDiscoveryValue(this DiscoveryOptions source, XBeeProtocol protocol, ISet options)
+ {
+ // Calculate value to be configured.
+ int value = 0;
+ switch (protocol)
+ {
+ case XBeeProtocol.ZIGBEE:
+ case XBeeProtocol.ZNET:
+ foreach (DiscoveryOptions op in options)
+ {
+ if (op == DiscoveryOptions.APPEND_RSSI)
+ continue;
+ value = value + op.GetValue();
+ }
+ break;
+ case XBeeProtocol.DIGI_MESH:
+ case XBeeProtocol.DIGI_POINT:
+ case XBeeProtocol.XLR:
+ // TODO [XLR_DM] The next version of the XLR will add DigiMesh support.
+ // For the moment only point-to-multipoint is supported in this kind of devices.
+ case XBeeProtocol.XLR_DM:
+ foreach (DiscoveryOptions op in options)
+ value = value + op.GetValue();
+ break;
+ case XBeeProtocol.RAW_802_15_4:
+ case XBeeProtocol.UNKNOWN:
+ default:
+ if (options.Contains(DiscoveryOptions.DISCOVER_MYSELF))
+ value = 1; // This is different for 802.15.4.
+ break;
+ }
+ return value;
+ }
+
+ ///
+ /// Returns the object in string format.
+ ///
+ ///
+ /// The object in string format.
+ public static string ToDisplayString(this DiscoveryOptions source)
+ {
+ var value = lookupTable[source];
+
+ return string.Format("{0} ({1})", value, (byte)source);
+ }
+ }
}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/ExplicitXBeeMessage.cs b/XBeeLibrary.Core/Models/ExplicitXBeeMessage.cs
new file mode 100644
index 0000000..10c7cb9
--- /dev/null
+++ b/XBeeLibrary.Core/Models/ExplicitXBeeMessage.cs
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an Explicit XBee message containing the remote XBee device the message
+ /// belongs to, the content (data) of the message, a flag indicating if the message is a broadcast
+ /// message (was received or is being sent via broadcast) and all the application layer fields:
+ /// source endpoint, destination endpoint, cluster ID and profile ID.
+ ///
+ ///
+ /// This class is used within the XBee C# Library to read explicit data sent by remote devices.
+ ///
+ public class ExplicitXBeeMessage : XBeeMessage
+ {
+ ///
+ /// Class constructor. Instantiates a new object of type with
+ /// the given parameters.
+ ///
+ /// The remote XBee device the message belongs to (device that
+ /// sent the message).
+ /// Endpoint of the source that initiated the transmission.
+ /// Endpoint of the destination the message was addressed to.
+ /// Cluster ID the packet was addressed to.
+ /// Profile ID the packet was addressed to.
+ /// Byte array containing the data of the message.
+ /// If sourceEndpoint.Length != 2
+ /// or if destEndpoint.Length != 2.
+ /// If remoteXBeeDevice == null
+ /// or if data == null.
+ public ExplicitXBeeMessage(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data)
+ : this(remoteXBeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data, false) { }
+
+ ///
+ /// Class constructor. Instantiates a new object of type ExplicitXBeeMessage
+ /// with the given parameters.
+ ///
+ /// The remote XBee device the message belongs to
+ /// (device that sent the message).
+ /// Endpoint of the source that initiated the transmission.
+ /// Endpoint of the destination the message was addressed to.
+ /// Cluster ID the packet was addressed to.
+ /// Profile ID the packet was addressed to.
+ /// Byte array containing the data of the message.
+ /// Indicates if the message was received via broadcast.
+ /// If sourceEndpoint.Length != 2 or
+ /// if destEndpoint.Length != 2.
+ /// If remoteXBeeDevice == null or
+ /// if data == null.
+ public ExplicitXBeeMessage(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint,
+ byte[] clusterID, byte[] profileID, byte[] data, bool isBroadcast)
+ : base(remoteXBeeDevice, data, isBroadcast)
+ {
+ if (clusterID.Length != 2)
+ throw new ArgumentException("Cluster ID must be 2 bytes.");
+ if (profileID.Length != 2)
+ throw new ArgumentException("Profile ID must be 2 bytes.");
+
+ SourceEndpoint = sourceEndpoint;
+ DestEndpoint = destEndpoint;
+ ClusterID = clusterID;
+ ProfileID = profileID;
+ }
+
+ // Properties.
+ ///
+ /// The endpoint of the source that initiated the transmission.
+ ///
+ public byte SourceEndpoint { get; private set; }
+
+ ///
+ /// The endpoint of the destination the message was addressed to.
+ ///
+ public byte DestEndpoint { get; private set; }
+
+ ///
+ /// The cluster ID the packet was addressed to.
+ ///
+ public byte[] ClusterID { get; private set; }
+
+ ///
+ /// The profile ID the packet was addressed to.
+ ///
+ public byte[] ProfileID { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/Format.cs b/XBeeLibrary.Core/Models/Format.cs
new file mode 100644
index 0000000..e3b25d1
--- /dev/null
+++ b/XBeeLibrary.Core/Models/Format.cs
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different field formats of XBee settings.
+ ///
+ public enum Format
+ {
+ // Enumeration entries.
+ HEX,
+ ASCII,
+ IPV4,
+ IPV6,
+ PHONE,
+ NOFORMAT,
+ UNKNOWN
+ }
+
+ public static class FormatExtensions
+ {
+ // Variables.
+ static IDictionary lookupTable = new Dictionary();
+
+ static FormatExtensions()
+ {
+ lookupTable.Add(Format.HEX, "hexadecimal");
+ lookupTable.Add(Format.ASCII, "ASCII");
+ lookupTable.Add(Format.IPV4, "IPv4");
+ lookupTable.Add(Format.IPV6, "IPv6");
+ lookupTable.Add(Format.PHONE, "phone");
+ lookupTable.Add(Format.NOFORMAT, "No format");
+ lookupTable.Add(Format.UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Retrieves the Format identifier.
+ ///
+ ///
+ /// The format id.
+ public static Format GetIdentifier(this Format source)
+ {
+ return source;
+ }
+
+ ///
+ /// Retrieves the Format description.
+ ///
+ ///
+ /// The format description.
+ public static string GetDescription(this Format source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Retrieves the for the given .
+ ///
+ ///
+ /// ID value to retrieve .
+ /// The associated with the given ,
+ /// if it does not exist.
+ public static Format Get(this Format source, string identifier)
+ {
+ var values = Enum.GetValues(typeof(Format)).OfType();
+
+ foreach (var value in values)
+ {
+ if (value.ToString().Equals(identifier))
+ return value;
+ }
+
+ return Format.NOFORMAT;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this Format source)
+ {
+ return GetDescription(source);
+ }
+
+ ///
+ /// Returns all the possible values in regex format (separated by '|').
+ ///
+ /// All the possible values in regex format.
+ public static string GetAllValues()
+ {
+ string values = "";
+ var formats = Enum.GetValues(typeof(Format)).OfType();
+ foreach (Format format in formats)
+ {
+ values += format.ToDisplayString();
+ values += "|";
+ }
+ // Remove last character added.
+ return values.Remove(values.Length - 1);
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/HardwareVersion.cs b/XBeeLibrary.Core/Models/HardwareVersion.cs
new file mode 100644
index 0000000..9c013e4
--- /dev/null
+++ b/XBeeLibrary.Core/Models/HardwareVersion.cs
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents the hardware version number of an XBee device.
+ ///
+ public class HardwareVersion : IEquatable
+ {
+ // Constants.
+ private const int HASH_SEED = 23;
+
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The hardware version numeric value.
+ /// The hardware version description.
+ /// If is null.
+ /// If 0
+ /// or if Length of is lower than 1.
+ private HardwareVersion(int value, string description)
+ {
+ if (string.IsNullOrEmpty(description))
+ throw new ArgumentNullException("Description cannot be null or empty.");
+ if (value < 0)
+ throw new ArgumentException("Value cannot be less than 0.");
+
+ Value = value;
+ Description = description;
+ }
+
+ // Properties.
+ ///
+ /// The Hardware version numeric value.
+ ///
+ public int Value { get; private set; }
+
+ ///
+ /// The Hardware version description.
+ ///
+ public string Description { get; private set; }
+
+ ///
+ /// Gets the object associated to the given numeric value.
+ ///
+ /// Numeric value of the retrieve.
+ /// The associated to the specified ,
+ /// null if there is not any with the .
+ public static HardwareVersion Get(int value)
+ {
+ var hvEnum = HardwareVersionEnum.ABANDONATED.Get(value);
+ return new HardwareVersion(hvEnum.GetValue(), hvEnum.GetDescription());
+ }
+
+ ///
+ /// Gets the object associated to the specified numeric
+ /// and .
+ ///
+ /// Numeric value of the retrieve.
+ /// Description of the retrieve.
+ /// The associated to the given value and description
+ /// if is null.
+ /// if < 0 or Length of
+ /// is lower than 1.
+ public static HardwareVersion Get(int value, string description)
+ {
+ return new HardwareVersion(value, description);
+ }
+
+ ///
+ /// Returns whether this object is equal to the given one.
+ ///
+ /// Object to compare if it is equal to the caller one.
+ /// true if the caller/this object is equal to ,
+ /// false otherwise.
+ public override bool Equals(object obj)
+ {
+ HardwareVersion other = obj as HardwareVersion;
+ return other != null && Equals(other);
+ }
+
+ ///
+ /// Returns whether this is equal to the given one.
+ ///
+ /// to compare if it is equal to
+ /// the caller one.
+ /// true if the caller/this object is equal to ,
+ /// false otherwise.
+ public bool Equals(HardwareVersion other)
+ {
+ return other != null
+ && other.Value == Value
+ && other.Description == Description;
+ }
+
+ ///
+ /// Returns the Hash code of this object.
+ ///
+ /// The Hash code of this object.
+ public override int GetHashCode()
+ {
+ int hash = HASH_SEED * (HASH_SEED + Value);
+ return hash;
+ }
+
+ ///
+ /// Returns a string representation of this object.
+ ///
+ /// A string representation of this object.
+ public override string ToString()
+ {
+ return Value.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary/Models/HardwareVersionEnum.cs b/XBeeLibrary.Core/Models/HardwareVersionEnum.cs
similarity index 62%
rename from XBeeLibrary/Models/HardwareVersionEnum.cs
rename to XBeeLibrary.Core/Models/HardwareVersionEnum.cs
index 4d9eb93..25f5de8 100644
--- a/XBeeLibrary/Models/HardwareVersionEnum.cs
+++ b/XBeeLibrary.Core/Models/HardwareVersionEnum.cs
@@ -1,152 +1,218 @@
-using Kveer.XBeeApi.Utils;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates the different hardware versions of the XBee devices.
- ///
- public enum HardwareVersionEnum
- {
- X09_009 = 1,
- X09_019 = 2,
- XH9_009 = 3,
- XH9_019 = 4,
- X24_009 = 5,
- X24_019 = 6,
- X09_001 = 7,
- XH9_001 = 8,
- X08_004 = 9,
- XC09_009 = 0xa,
- XC09_038 = 0xb,
- X24_038 = 0xc,
- X09_009_TX = 0xd,
- X09_019_TX = 0xe,
- XH9_009_TX = 0xf,
- XH9_019_TX = 0x10,
- X09_001_TX = 0x11,
- XH9_001_TX = 0x12,
- XT09B_XXX = 0x13,
- XT09_XXX = 0x14,
- XC08_009 = 0x15,
- XC08_038 = 0x16,
- XB24_AXX_XX = 0x17,
- XBP24_AXX_XX = 0x18,
- XB24_BXIX_XXX = 0x19,
- XBP24_BXIX_XXX = 0x1a,
- XBP09_DXIX_XXX = 0x1b,
- XBP09_XCXX_XXX = 0x1c,
- XBP08_DXXX_XXX = 0x1d,
- XBP24B = 0x1e,
- XB24_WF = 0x1f,
- AMBER_MBUS = 0x20,
- XBP24C = 0x21,
- XB24C = 0x22,
- XSC_GEN3 = 0x23,
- SRD_868_GEN3 = 0x24,
- ABANDONATED = 0x25,
- SMT_900LP = 0x26,
- WIFI_ATHEROS = 0x27,
- SMT_WIFI_ATHEROS = 0x28,
- SMT_475LP = 0x29,
- XBEE_CELL_TH = 0x2a,
- XLR_MODULE = 0x2b,
- XB900HP_NZ = 0x2c,
- XBP24C_TH_DIP = 0x2d,
- XB24C_TH_DIP = 0x2e,
- XLR_BASEBOARD = 0x2f
- }
-
- public static class HardwareVersionEnumExtensions
- {
- static IDictionary lookupTable = new Dictionary();
-
- static HardwareVersionEnumExtensions()
- {
- lookupTable.Add(HardwareVersionEnum.X09_009, "X09-009");
- lookupTable.Add(HardwareVersionEnum.X09_019, "X09-019");
- lookupTable.Add(HardwareVersionEnum.XH9_009, "XH9-009");
- lookupTable.Add(HardwareVersionEnum.XH9_019, "XH9-019");
- lookupTable.Add(HardwareVersionEnum.X24_009, "X24-009");
- lookupTable.Add(HardwareVersionEnum.X24_019, "X24-019");
- lookupTable.Add(HardwareVersionEnum.X09_001, "X09-001");
- lookupTable.Add(HardwareVersionEnum.XH9_001, "XH9-001");
- lookupTable.Add(HardwareVersionEnum.X08_004, "X08-004");
- lookupTable.Add(HardwareVersionEnum.XC09_009, "XC09-009");
- lookupTable.Add(HardwareVersionEnum.XC09_038, "XC09-038");
- lookupTable.Add(HardwareVersionEnum.X24_038, "X24-038");
- lookupTable.Add(HardwareVersionEnum.X09_009_TX, "X09-009-TX");
- lookupTable.Add(HardwareVersionEnum.X09_019_TX, "X09-019-TX");
- lookupTable.Add(HardwareVersionEnum.XH9_009_TX, "XH9-009-TX");
- lookupTable.Add(HardwareVersionEnum.XH9_019_TX, "XH9-019-TX");
- lookupTable.Add(HardwareVersionEnum.X09_001_TX, "X09-001-TX");
- lookupTable.Add(HardwareVersionEnum.XH9_001_TX, "XH9-001-TX");
- lookupTable.Add(HardwareVersionEnum.XT09B_XXX, "XT09B-xxx (Attenuator version)");
- lookupTable.Add(HardwareVersionEnum.XT09_XXX, "XT09-xxx");
- lookupTable.Add(HardwareVersionEnum.XC08_009, "XC08-009");
- lookupTable.Add(HardwareVersionEnum.XC08_038, "XC08-038");
- lookupTable.Add(HardwareVersionEnum.XB24_AXX_XX, "XB24-Axx-xx");
- lookupTable.Add(HardwareVersionEnum.XBP24_AXX_XX, "XBP24-Axx-xx");
- lookupTable.Add(HardwareVersionEnum.XB24_BXIX_XXX, "XB24-BxIx-xxx and XB24-Z7xx-xxx");
- lookupTable.Add(HardwareVersionEnum.XBP24_BXIX_XXX, "XBP24-BxIx-xxx and XBP24-Z7xx-xxx");
- lookupTable.Add(HardwareVersionEnum.XBP09_DXIX_XXX, "XBP09-DxIx-xxx Digi Mesh");
- lookupTable.Add(HardwareVersionEnum.XBP09_XCXX_XXX, "XBP09-XCxx-xxx: S3 XSC Compatibility");
- lookupTable.Add(HardwareVersionEnum.XBP08_DXXX_XXX, "XBP08-Dxx-xxx 868MHz");
- lookupTable.Add(HardwareVersionEnum.XBP24B, "XBP24B: Low cost ZB PRO and PLUS S2B");
- lookupTable.Add(HardwareVersionEnum.XB24_WF, "XB24-WF: XBee 802.11 (Redpine module)");
- lookupTable.Add(HardwareVersionEnum.AMBER_MBUS, "??????: M-Bus module made by Amber");
- lookupTable.Add(HardwareVersionEnum.XBP24C, "XBP24C: XBee PRO SMT Ember 357 S2C PRO");
- lookupTable.Add(HardwareVersionEnum.XB24C, "XB24C: XBee SMT Ember 357 S2C");
- lookupTable.Add(HardwareVersionEnum.XSC_GEN3, "XSC_GEN3: XBP9 XSC 24 dBm");
- lookupTable.Add(HardwareVersionEnum.SRD_868_GEN3, "SDR_868_GEN3: XB8 12 dBm");
- lookupTable.Add(HardwareVersionEnum.ABANDONATED, "Abandonated");
- lookupTable.Add(HardwareVersionEnum.SMT_900LP, "900LP (SMT): 900LP on 'S8 HW'");
- lookupTable.Add(HardwareVersionEnum.WIFI_ATHEROS, "WiFi Atheros (TH-DIP) XB2S-WF");
- lookupTable.Add(HardwareVersionEnum.SMT_WIFI_ATHEROS, "WiFi Atheros (SMT) XB2B-WF");
- lookupTable.Add(HardwareVersionEnum.SMT_475LP, "475LP (SMT): Beta 475MHz");
- lookupTable.Add(HardwareVersionEnum.XBEE_CELL_TH, "XBee-Cell (TH): XBee Cellular");
- lookupTable.Add(HardwareVersionEnum.XLR_MODULE, "XLR Module");
- lookupTable.Add(HardwareVersionEnum.XB900HP_NZ, "XB900HP (New Zealand): XB9 NZ HW/SW");
- lookupTable.Add(HardwareVersionEnum.XBP24C_TH_DIP, "XBP24C (TH-DIP): XBee PRO DIP");
- lookupTable.Add(HardwareVersionEnum.XB24C_TH_DIP, "XB24C (TH-DIP): XBee DIP");
- lookupTable.Add(HardwareVersionEnum.XLR_BASEBOARD, "XLR Baseboard");
- }
-
- ///
- /// Gets the Hardware version numeric value.
- ///
- ///
- /// The hardware version numeric value.
- public static int GetValue(this HardwareVersionEnum source)
- {
- return (int)source;
- }
-
- ///
- /// Gets the hardware version description.
- ///
- ///
- /// The hardware version description.
- public static string GetDescription(this HardwareVersionEnum source)
- {
- return lookupTable[source];
- }
-
- ///
- /// Gets the associated to the given numeric value.
- ///
- ///
- /// Numeric value of the to retrieve.
- /// The associated to the given numeric value.
- public static HardwareVersionEnum Get(this HardwareVersionEnum dumb, int value)
- {
- return (HardwareVersionEnum)value;
- }
-
- public static string ToDisplayString(this HardwareVersionEnum source)
- {
- return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source.GetValue()), source.GetDescription());
- }
- }
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System.Collections.Generic;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different hardware versions of the XBee devices.
+ ///
+ public enum HardwareVersionEnum
+ {
+ // Enumeration entries.
+ X09_009 = 1,
+ X09_019 = 2,
+ XH9_009 = 3,
+ XH9_019 = 4,
+ X24_009 = 5,
+ X24_019 = 6,
+ X09_001 = 7,
+ XH9_001 = 8,
+ X08_004 = 9,
+ XC09_009 = 0xa,
+ XC09_038 = 0xb,
+ X24_038 = 0xc,
+ X09_009_TX = 0xd,
+ X09_019_TX = 0xe,
+ XH9_009_TX = 0xf,
+ XH9_019_TX = 0x10,
+ X09_001_TX = 0x11,
+ XH9_001_TX = 0x12,
+ XT09B_XXX = 0x13,
+ XT09_XXX = 0x14,
+ XC08_009 = 0x15,
+ XC08_038 = 0x16,
+ XB24_AXX_XX = 0x17,
+ XBP24_AXX_XX = 0x18,
+ XB24_BXIX_XXX = 0x19,
+ XBP24_BXIX_XXX = 0x1a,
+ XBP09_DXIX_XXX = 0x1b,
+ XBP09_XCXX_XXX = 0x1c,
+ XBP08_DXXX_XXX = 0x1d,
+ XBP24B = 0x1e,
+ XB24_WF = 0x1f,
+ AMBER_MBUS = 0x20,
+ XBP24C = 0x21,
+ XB24C = 0x22,
+ XSC_GEN3 = 0x23,
+ SRD_868_GEN3 = 0x24,
+ ABANDONATED = 0x25,
+ SMT_900LP = 0x26,
+ WIFI_ATHEROS = 0x27,
+ SMT_WIFI_ATHEROS = 0x28,
+ SMT_475LP = 0x29,
+ XBEE_CELL_TH = 0x2a,
+ XLR_MODULE = 0x2b,
+ XB900HP_NZ = 0x2c,
+ XBP24C_TH_DIP = 0x2d,
+ XB24C_TH_DIP = 0x2e,
+ XLR_BASEBOARD = 0x2f,
+ XBP24C_S2C_SMT = 0x30,
+ SX_PRO = 0x31,
+ S2D_SMT_PRO = 0x32,
+ S2D_SMT_REG = 0x33,
+ S2D_TH_PRO = 0x34,
+ S2D_TH_REG = 0x35,
+ SX = 0x3E,
+ XTR = 0x3F,
+ CELLULAR_CAT1_LTE_VERIZON = 0x40,
+ XBEE3_MICRO = 0x41,
+ XBEE3_TH = 0x42,
+ XBEE3_RESERVED = 0x43,
+ CELLULAR_3G = 0x44,
+ XB8X = 0x45,
+ CELLULAR_LTE_VERIZON = 0x46, // Abandoned
+ CELLULAR_LTE_ATT = 0x47,
+ CELLULAR_NBIOT_EUROPE = 0x48, // Never released
+ CELLULAR_3_CAT1_LTE_ATT = 0x49,
+ CELLULAR_3_LTE_M_VERIZON = 0x4A, // Abandoned
+ CELLULAR_3_LTE_M_ATT = 0x4B,
+ CELLULAR_3_LTE_M_ATT_TELIT = 0x4C, // Never released
+ CELLULAR_3_CAT1_LTE_VERIZON = 0x4D
+ }
+
+ public static class HardwareVersionEnumExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static HardwareVersionEnumExtensions()
+ {
+ lookupTable.Add(HardwareVersionEnum.X09_009, "X09-009");
+ lookupTable.Add(HardwareVersionEnum.X09_019, "X09-019");
+ lookupTable.Add(HardwareVersionEnum.XH9_009, "XH9-009");
+ lookupTable.Add(HardwareVersionEnum.XH9_019, "XH9-019");
+ lookupTable.Add(HardwareVersionEnum.X24_009, "X24-009");
+ lookupTable.Add(HardwareVersionEnum.X24_019, "X24-019");
+ lookupTable.Add(HardwareVersionEnum.X09_001, "X09-001");
+ lookupTable.Add(HardwareVersionEnum.XH9_001, "XH9-001");
+ lookupTable.Add(HardwareVersionEnum.X08_004, "X08-004");
+ lookupTable.Add(HardwareVersionEnum.XC09_009, "XC09-009");
+ lookupTable.Add(HardwareVersionEnum.XC09_038, "XC09-038");
+ lookupTable.Add(HardwareVersionEnum.X24_038, "X24-038");
+ lookupTable.Add(HardwareVersionEnum.X09_009_TX, "X09-009-TX");
+ lookupTable.Add(HardwareVersionEnum.X09_019_TX, "X09-019-TX");
+ lookupTable.Add(HardwareVersionEnum.XH9_009_TX, "XH9-009-TX");
+ lookupTable.Add(HardwareVersionEnum.XH9_019_TX, "XH9-019-TX");
+ lookupTable.Add(HardwareVersionEnum.X09_001_TX, "X09-001-TX");
+ lookupTable.Add(HardwareVersionEnum.XH9_001_TX, "XH9-001-TX");
+ lookupTable.Add(HardwareVersionEnum.XT09B_XXX, "XT09B-xxx (Attenuator version)");
+ lookupTable.Add(HardwareVersionEnum.XT09_XXX, "XT09-xxx");
+ lookupTable.Add(HardwareVersionEnum.XC08_009, "XC08-009");
+ lookupTable.Add(HardwareVersionEnum.XC08_038, "XC08-038");
+ lookupTable.Add(HardwareVersionEnum.XB24_AXX_XX, "XB24-Axx-xx");
+ lookupTable.Add(HardwareVersionEnum.XBP24_AXX_XX, "XBP24-Axx-xx");
+ lookupTable.Add(HardwareVersionEnum.XB24_BXIX_XXX, "XB24-BxIx-xxx and XB24-Z7xx-xxx");
+ lookupTable.Add(HardwareVersionEnum.XBP24_BXIX_XXX, "XBP24-BxIx-xxx and XBP24-Z7xx-xxx");
+ lookupTable.Add(HardwareVersionEnum.XBP09_DXIX_XXX, "XBP09-DxIx-xxx Digi Mesh");
+ lookupTable.Add(HardwareVersionEnum.XBP09_XCXX_XXX, "XBP09-XCxx-xxx: S3 XSC Compatibility");
+ lookupTable.Add(HardwareVersionEnum.XBP08_DXXX_XXX, "XBP08-Dxx-xxx 868MHz");
+ lookupTable.Add(HardwareVersionEnum.XBP24B, "XBP24B: Low cost ZB PRO and PLUS S2B");
+ lookupTable.Add(HardwareVersionEnum.XB24_WF, "XB24-WF: XBee 802.11 (Redpine module)");
+ lookupTable.Add(HardwareVersionEnum.AMBER_MBUS, "??????: M-Bus module made by Amber");
+ lookupTable.Add(HardwareVersionEnum.XBP24C, "XBP24C: XBee PRO SMT Ember 357 S2C PRO");
+ lookupTable.Add(HardwareVersionEnum.XB24C, "XB24C: XBee SMT Ember 357 S2C");
+ lookupTable.Add(HardwareVersionEnum.XSC_GEN3, "XSC_GEN3: XBP9 XSC 24 dBm");
+ lookupTable.Add(HardwareVersionEnum.SRD_868_GEN3, "SDR_868_GEN3: XB8 12 dBm");
+ lookupTable.Add(HardwareVersionEnum.ABANDONATED, "Abandonated");
+ lookupTable.Add(HardwareVersionEnum.SMT_900LP, "900LP (SMT): 900LP on 'S8 HW'");
+ lookupTable.Add(HardwareVersionEnum.WIFI_ATHEROS, "WiFi Atheros (TH-DIP) XB2S-WF");
+ lookupTable.Add(HardwareVersionEnum.SMT_WIFI_ATHEROS, "WiFi Atheros (SMT) XB2B-WF");
+ lookupTable.Add(HardwareVersionEnum.SMT_475LP, "475LP (SMT): Beta 475MHz");
+ lookupTable.Add(HardwareVersionEnum.XBEE_CELL_TH, "XBee-Cell (TH): XBee Cellular");
+ lookupTable.Add(HardwareVersionEnum.XLR_MODULE, "XLR Module");
+ lookupTable.Add(HardwareVersionEnum.XB900HP_NZ, "XB900HP (New Zealand): XB9 NZ HW/SW");
+ lookupTable.Add(HardwareVersionEnum.XBP24C_TH_DIP, "XBP24C (TH-DIP): XBee PRO DIP");
+ lookupTable.Add(HardwareVersionEnum.XB24C_TH_DIP, "XB24C (TH-DIP): XBee DIP");
+ lookupTable.Add(HardwareVersionEnum.XLR_BASEBOARD, "XLR Baseboard");
+ lookupTable.Add(HardwareVersionEnum.XBP24C_S2C_SMT, "XBee PRO SMT");
+ lookupTable.Add(HardwareVersionEnum.SX_PRO, "SX Pro");
+ lookupTable.Add(HardwareVersionEnum.S2D_SMT_PRO, "XBP24D: S2D SMT PRO");
+ lookupTable.Add(HardwareVersionEnum.S2D_SMT_REG, "XB24D: S2D SMT Reg");
+ lookupTable.Add(HardwareVersionEnum.S2D_TH_PRO, "XBP24D: S2D TH PRO");
+ lookupTable.Add(HardwareVersionEnum.S2D_TH_REG, "XB24D: S2D TH Reg");
+ lookupTable.Add(HardwareVersionEnum.SX, "SX");
+ lookupTable.Add(HardwareVersionEnum.XTR, "XTR");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_CAT1_LTE_VERIZON, "XBee Cellular Cat 1 LTE Verizon");
+ lookupTable.Add(HardwareVersionEnum.XBEE3_MICRO, "XBee3 Micro/SMT");
+ lookupTable.Add(HardwareVersionEnum.XBEE3_TH, "XBee3 TH");
+ lookupTable.Add(HardwareVersionEnum.XBEE3_RESERVED, "XBee3 Reserved");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_3G, "XBee Cellular 3G");
+ lookupTable.Add(HardwareVersionEnum.XB8X, "XB8X");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_LTE_VERIZON, "XBee Cellular LTE-M Verizon");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_LTE_ATT, "XBee Cellular LTE-M AT&T");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_NBIOT_EUROPE, "XBee Cellular NBIoT Europe");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_3_CAT1_LTE_ATT, "XBee3 Cellular Cat 1 LTE AT&T");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_3_LTE_M_VERIZON, "XBee3 Cellular LTE-M Verizon");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_3_LTE_M_ATT, "XBee3 Cellular LTE-M AT&T (u-blox)");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_3_LTE_M_ATT_TELIT, "XBee3 Cellular LTE-M AT&T (Telit)");
+ lookupTable.Add(HardwareVersionEnum.CELLULAR_3_CAT1_LTE_VERIZON, "XBee3 Cellular Cat 1 LTE Verizon");
+ }
+
+ ///
+ /// Gets the Hardware version numeric value.
+ ///
+ ///
+ /// The hardware version numeric value.
+ public static int GetValue(this HardwareVersionEnum source)
+ {
+ return (int)source;
+ }
+
+ ///
+ /// Gets the hardware version description.
+ ///
+ ///
+ /// The hardware version description.
+ public static string GetDescription(this HardwareVersionEnum source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the associated to the given numeric value.
+ ///
+ ///
+ /// Numeric value of the to retrieve.
+ /// The associated to the given numeric value.
+ public static HardwareVersionEnum Get(this HardwareVersionEnum source, int value)
+ {
+ return (HardwareVersionEnum)value;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this HardwareVersionEnum source)
+ {
+ return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source.GetValue()), source.GetDescription());
+ }
+ }
}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/IPMessage.cs b/XBeeLibrary.Core/Models/IPMessage.cs
new file mode 100644
index 0000000..d8d0ffd
--- /dev/null
+++ b/XBeeLibrary.Core/Models/IPMessage.cs
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Net;
+using System.Text;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an IP message containing the IP address the message belongs to, the
+ /// source and destination ports, the IP protocol, and the content (data) of the message.
+ ///
+ /// This class is used within the library to read data sent to IP devices.
+ public class IPMessage
+ {
+ ///
+ /// Class constructor. Instantiates a new object of type with the
+ /// given parameters.
+ ///
+ /// The IP address the message comes from.
+ /// TCP or UDP source port of the transmission.
+ /// TCP or UDP destination port of the transmission.
+ /// IP protocol used in the transmission.
+ /// Byte array containing the data of the message.
+ /// If is null
+ /// or if is null.
+ /// If is null or invalid,
+ /// or if is null or invalid,
+ /// or if is .
+ public IPMessage(IPAddress ipAddress, int sourcePort, int destPort, IPProtocol protocol, byte[] data)
+ {
+ if (protocol == IPProtocol.UNKNOWN)
+ throw new ArgumentException("Protocol cannot be unknown.");
+ if (sourcePort < 0 || sourcePort > 65535)
+ throw new ArgumentException("Source port must be between 0 and 65535.");
+ if (destPort < 0 || destPort > 65535)
+ throw new ArgumentException("Destination port must be between 0 and 65535.");
+
+ IPAddress = ipAddress ?? throw new ArgumentNullException("IP address cannot be null.");
+ SourcePort = sourcePort;
+ DestPort = destPort;
+ Protocol = protocol;
+ Data = data ?? throw new ArgumentNullException("Data cannot be null.");
+ }
+
+ // Properties.
+ ///
+ /// The IP address this message is associated to.
+ ///
+ ///
+ public IPAddress IPAddress { get; private set; }
+
+ ///
+ /// The source port of the transmission.
+ ///
+ public int SourcePort { get; private set; }
+
+ ///
+ /// The destination port of the transmission.
+ ///
+ public int DestPort { get; private set; }
+
+ ///
+ /// The IP protocol used in the transmission.
+ ///
+ ///
+ public IPProtocol Protocol { get; private set; }
+
+ ///
+ /// The byte array containing the data of the message.
+ ///
+ public byte[] Data { get; private set; }
+
+ ///
+ /// The data of the message in string format.
+ ///
+ public string DataString => Encoding.UTF8.GetString(Data);
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/IPProtocol.cs b/XBeeLibrary.Core/Models/IPProtocol.cs
new file mode 100644
index 0000000..61105ba
--- /dev/null
+++ b/XBeeLibrary.Core/Models/IPProtocol.cs
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different IP protocols.
+ ///
+ public enum IPProtocol
+ {
+ // Enumeration entries.
+ UDP = 0,
+ TCP = 1,
+ TCP_SSL = 4,
+ UNKNOWN = 99
+ }
+
+ public static class IPProtocolExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static IPProtocolExtensions()
+ {
+ lookupTable.Add(IPProtocol.UDP, "UDP");
+ lookupTable.Add(IPProtocol.TCP, "TCP");
+ lookupTable.Add(IPProtocol.TCP_SSL, "TCP SSL");
+ lookupTable.Add(IPProtocol.UNKNOWN, "UNKNOWN");
+ }
+
+ ///
+ /// Gets the IP protocol ID.
+ ///
+ ///
+ /// The IP protocol ID.
+ public static int GetID(this IPProtocol source)
+ {
+ return (int)source;
+ }
+
+ ///
+ /// Gets the IP protocol name.
+ ///
+ ///
+ /// The IP protocol name.
+ public static string GetName(this IPProtocol source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the IP protocol for the given ID.
+ ///
+ ///
+ /// ID value to retrieve .
+ /// The IP protocol for the given ID.,
+ /// if the could not be found in the list.
+ public static IPProtocol Get(this IPProtocol source, int id)
+ {
+ var values = Enum.GetValues(typeof(IPProtocol));
+
+ if (values.OfType().Contains(id))
+ return (IPProtocol)id;
+
+ return IPProtocol.UNKNOWN;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this IPProtocol source)
+ {
+ return lookupTable[source];
+ }
+ }
+}
diff --git a/XBeeLibrary/Models/ModemStatusEvent.cs b/XBeeLibrary.Core/Models/ModemStatusEvent.cs
similarity index 70%
rename from XBeeLibrary/Models/ModemStatusEvent.cs
rename to XBeeLibrary.Core/Models/ModemStatusEvent.cs
index 86af524..7cf3d8c 100644
--- a/XBeeLibrary/Models/ModemStatusEvent.cs
+++ b/XBeeLibrary.Core/Models/ModemStatusEvent.cs
@@ -1,101 +1,134 @@
-using Kveer.XBeeApi.Utils;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates the different modem status events. This enumeration list is intended to be used within the packet.
- ///
- public enum ModemStatusEvent
- {
-
- STATUS_HARDWARE_RESET = 0,
- STATUS_WATCHDOG_TIMER_RESET = 1,
- STATUS_JOINED_NETWORK = 2,
- STATUS_DISASSOCIATED = 3,
- STATUS_ERROR_SYNCHRONIZATION_LOST = 4,
- STATUS_COORDINATOR_REALIGNMENT = 5,
- STATUS_COORDINATOR_STARTED = 6,
- STATUS_NETWORK_SECURITY_KEY_UPDATED = 7,
- STATUS_NETWORK_WOKE_UP = 0xb,
- STATUS_NETWORK_WENT_TO_SLEEP = 0xc,
- STATUS_VOLTAGE_SUPPLY_LIMIT_EXCEEDED = 0xd,
- STATUS_MODEM_CONFIG_CHANGED_WHILE_JOINING = 0x11,
- STATUS_ERROR_STACK = 0x80,
- STATUS_ERROR_AP_NOT_CONNECTED = 0x82,
- STATUS_ERROR_AP_NOT_FOUND = 0x83,
- STATUS_ERROR_PSK_NOT_CONFIGURED = 0x84,
- STATUS_ERROR_SSID_NOT_FOUND = 0x87,
- STATUS_ERROR_FAILED_JOIN_SECURITY = 0x88,
- STATUS_ERROR_INVALID_CHANNEL = 0x8a,
- STATUS_ERROR_FAILED_JOIN_AP = 0x8e,
- STATUS_UNKNOWN = 0xff
- }
-
- public static class ModemStatusEventStructExtensions
- {
- static IDictionary lookupTable = new Dictionary();
-
- static ModemStatusEventStructExtensions()
- {
- lookupTable.Add(ModemStatusEvent.STATUS_HARDWARE_RESET, "Device was reset");
- lookupTable.Add(ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET, "Watchdog timer was reset");
- lookupTable.Add(ModemStatusEvent.STATUS_JOINED_NETWORK, "Device joined to network");
- lookupTable.Add(ModemStatusEvent.STATUS_DISASSOCIATED, "Device disassociated");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_SYNCHRONIZATION_LOST, "Configuration error/synchronization lost");
- lookupTable.Add(ModemStatusEvent.STATUS_COORDINATOR_REALIGNMENT, "Coordinator realignment");
- lookupTable.Add(ModemStatusEvent.STATUS_COORDINATOR_STARTED, "The coordinator started");
- lookupTable.Add(ModemStatusEvent.STATUS_NETWORK_SECURITY_KEY_UPDATED, "Network security key was updated");
- lookupTable.Add(ModemStatusEvent.STATUS_NETWORK_WOKE_UP, "Network Woke Up");
- lookupTable.Add(ModemStatusEvent.STATUS_NETWORK_WENT_TO_SLEEP, "Network Went To Sleep");
- lookupTable.Add(ModemStatusEvent.STATUS_VOLTAGE_SUPPLY_LIMIT_EXCEEDED, "Voltage supply limit exceeded");
- lookupTable.Add(ModemStatusEvent.STATUS_MODEM_CONFIG_CHANGED_WHILE_JOINING, " Modem configuration changed while joining");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_STACK, "Stack error");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_AP_NOT_CONNECTED, "Send/join command issued without connecting from AP");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_AP_NOT_FOUND, "Access point not found");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_PSK_NOT_CONFIGURED, "PSK not configured");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_SSID_NOT_FOUND, "SSID not found");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_FAILED_JOIN_SECURITY, "Failed to join with security enabled");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_INVALID_CHANNEL, "Invalid channel");
- lookupTable.Add(ModemStatusEvent.STATUS_ERROR_FAILED_JOIN_AP, "Failed to join access point");
- lookupTable.Add(ModemStatusEvent.STATUS_UNKNOWN, "UNKNOWN");
- }
-
- public static int GetId(this ModemStatusEvent source)
- {
- return (int)source;
- }
-
- ///
- /// Gets the modem status description.
- ///
- ///
- /// Modem status description.
- public static string GetDescription(this ModemStatusEvent source)
- {
- return lookupTable[source];
- }
-
- ///
- /// Gets the associated to the given ID.
- ///
- /// ID of the to retrieve.
- /// The associated with the given ID.
- public static ModemStatusEvent Get(int id)
- {
- var values = Enum.GetValues(typeof(ModemStatusEvent));
-
- if (values.OfType().Contains(id))
- return (ModemStatusEvent)id;
-
- return ModemStatusEvent.STATUS_UNKNOWN;
- }
-
- public static string ToDisplayString(this ModemStatusEvent source)
- {
- return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)(int)source), source.GetDescription());
- }
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Packet.Common;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different modem status events. This enumeration list is intended to be used
+ /// within the packet.
+ ///
+ public enum ModemStatusEvent
+ {
+ // Enumeration entries.
+ STATUS_HARDWARE_RESET = 0,
+ STATUS_WATCHDOG_TIMER_RESET = 1,
+ STATUS_JOINED_NETWORK = 2,
+ STATUS_DISASSOCIATED = 3,
+ STATUS_ERROR_SYNCHRONIZATION_LOST = 4,
+ STATUS_COORDINATOR_REALIGNMENT = 5,
+ STATUS_COORDINATOR_STARTED = 6,
+ STATUS_NETWORK_SECURITY_KEY_UPDATED = 7,
+ STATUS_NETWORK_WOKE_UP = 0xb,
+ STATUS_NETWORK_WENT_TO_SLEEP = 0xc,
+ STATUS_VOLTAGE_SUPPLY_LIMIT_EXCEEDED = 0xd,
+ STATUS_MODEM_CONFIG_CHANGED_WHILE_JOINING = 0x11,
+ STATUS_BLE_CONNECTED = 0x32,
+ STATUS_BLE_DISCONNECTED = 0x33,
+ STATUS_ERROR_STACK = 0x80,
+ STATUS_ERROR_AP_NOT_CONNECTED = 0x82,
+ STATUS_ERROR_AP_NOT_FOUND = 0x83,
+ STATUS_ERROR_PSK_NOT_CONFIGURED = 0x84,
+ STATUS_ERROR_SSID_NOT_FOUND = 0x87,
+ STATUS_ERROR_FAILED_JOIN_SECURITY = 0x88,
+ STATUS_ERROR_INVALID_CHANNEL = 0x8a,
+ STATUS_ERROR_FAILED_JOIN_AP = 0x8e,
+ STATUS_UNKNOWN = 0xff
+ }
+
+ public static class ModemStatusEventStructExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static ModemStatusEventStructExtensions()
+ {
+ lookupTable.Add(ModemStatusEvent.STATUS_HARDWARE_RESET, "Device was reset");
+ lookupTable.Add(ModemStatusEvent.STATUS_WATCHDOG_TIMER_RESET, "Watchdog timer was reset");
+ lookupTable.Add(ModemStatusEvent.STATUS_JOINED_NETWORK, "Device joined to network");
+ lookupTable.Add(ModemStatusEvent.STATUS_DISASSOCIATED, "Device disassociated");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_SYNCHRONIZATION_LOST, "Configuration error/synchronization lost");
+ lookupTable.Add(ModemStatusEvent.STATUS_COORDINATOR_REALIGNMENT, "Coordinator realignment");
+ lookupTable.Add(ModemStatusEvent.STATUS_COORDINATOR_STARTED, "The coordinator started");
+ lookupTable.Add(ModemStatusEvent.STATUS_NETWORK_SECURITY_KEY_UPDATED, "Network security key was updated");
+ lookupTable.Add(ModemStatusEvent.STATUS_NETWORK_WOKE_UP, "Network Woke Up");
+ lookupTable.Add(ModemStatusEvent.STATUS_NETWORK_WENT_TO_SLEEP, "Network Went To Sleep");
+ lookupTable.Add(ModemStatusEvent.STATUS_VOLTAGE_SUPPLY_LIMIT_EXCEEDED, "Voltage supply limit exceeded");
+ lookupTable.Add(ModemStatusEvent.STATUS_MODEM_CONFIG_CHANGED_WHILE_JOINING, "Modem configuration changed while joining");
+ lookupTable.Add(ModemStatusEvent.STATUS_BLE_CONNECTED, "BLE connection unlocked");
+ lookupTable.Add(ModemStatusEvent.STATUS_BLE_DISCONNECTED, "BLE connection locked");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_STACK, "Stack error");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_AP_NOT_CONNECTED, "Send/join command issued without connecting from AP");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_AP_NOT_FOUND, "Access point not found");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_PSK_NOT_CONFIGURED, "PSK not configured");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_SSID_NOT_FOUND, "SSID not found");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_FAILED_JOIN_SECURITY, "Failed to join with security enabled");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_INVALID_CHANNEL, "Invalid channel");
+ lookupTable.Add(ModemStatusEvent.STATUS_ERROR_FAILED_JOIN_AP, "Failed to join access point");
+ lookupTable.Add(ModemStatusEvent.STATUS_UNKNOWN, "UNKNOWN");
+ }
+
+ ///
+ /// Gets the modem status ID
+ ///
+ ///
+ /// The modem status ID.
+ public static int GetId(this ModemStatusEvent source)
+ {
+ return (int)source;
+ }
+
+ ///
+ /// Gets the modem status description.
+ ///
+ ///
+ /// The modem status description.
+ public static string GetDescription(this ModemStatusEvent source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the associated to the given ID.
+ ///
+ /// ID of the to retrieve.
+ /// The associated with the given ID.
+ public static ModemStatusEvent Get(int id)
+ {
+ var values = Enum.GetValues(typeof(ModemStatusEvent));
+
+ if (values.OfType().Contains(id))
+ return (ModemStatusEvent)id;
+
+ return ModemStatusEvent.STATUS_UNKNOWN;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this ModemStatusEvent source)
+ {
+ return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)(int)source), source.GetDescription());
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/OperatingMode.cs b/XBeeLibrary.Core/Models/OperatingMode.cs
new file mode 100644
index 0000000..256f3b3
--- /dev/null
+++ b/XBeeLibrary.Core/Models/OperatingMode.cs
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System.Collections.Generic;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different working modes of the XBee device. The operating mode establishes the
+ /// way a user communicates with an XBee device through its serial interface.
+ ///
+ public enum OperatingMode
+ {
+ // Enumeration entries.
+ AT = 0,
+ API = 1,
+ API_ESCAPE = 2,
+ UNKNOWN = 3
+ }
+
+ public static class OperatingModeExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static OperatingModeExtensions()
+ {
+ lookupTable.Add(OperatingMode.AT, "AT mode");
+ lookupTable.Add(OperatingMode.API, "API mode");
+ lookupTable.Add(OperatingMode.API_ESCAPE, "API mode with escaped characters");
+ lookupTable.Add(OperatingMode.UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Gets the operating mode ID.
+ ///
+ ///
+ /// The operating mode ID.
+ public static int GetID(this OperatingMode source)
+ {
+ return (int)source;
+ }
+
+ ///
+ /// Gets the operating mode name.
+ ///
+ ///
+ /// The operating mode name.
+ public static string GetName(this OperatingMode source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this OperatingMode source)
+ {
+ return lookupTable[source];
+ }
+ }
+}
diff --git a/XBeeLibrary/Models/PowerLevel.cs b/XBeeLibrary.Core/Models/PowerLevel.cs
similarity index 57%
rename from XBeeLibrary/Models/PowerLevel.cs
rename to XBeeLibrary.Core/Models/PowerLevel.cs
index a3c1742..6a7912b 100644
--- a/XBeeLibrary/Models/PowerLevel.cs
+++ b/XBeeLibrary.Core/Models/PowerLevel.cs
@@ -1,78 +1,102 @@
-using Kveer.XBeeApi.Utils;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates the different power levels. The power level indicates the output power value of a radio when transmitting data.
- ///
- public enum PowerLevel : byte
- {
- // Enumeration entries
- LEVEL_LOWEST = 0x00,
- LEVEL_LOW = 0x01,
- LEVEL_MEDIUM = 0x02,
- LEVEL_HIGH = 0x03,
- LEVEL_HIGHEST = 0x04,
- LEVEL_UNKNOWN = 0xFF
- }
-
- public static class PowerLevelExtensions
- {
- private static IDictionary lookupTable = new Dictionary();
-
- static PowerLevelExtensions()
- {
- lookupTable.Add(PowerLevel.LEVEL_LOWEST, "Lowest");
- lookupTable.Add(PowerLevel.LEVEL_LOW, "Low");
- lookupTable.Add(PowerLevel.LEVEL_MEDIUM, "Medium");
- lookupTable.Add(PowerLevel.LEVEL_HIGH, "High");
- lookupTable.Add(PowerLevel.LEVEL_HIGHEST, "Highest");
- lookupTable.Add(PowerLevel.LEVEL_UNKNOWN, "Unknown");
- }
-
- ///
- /// Gets the power level value.
- ///
- ///
- /// The power level value.
- public static byte GetValue(this PowerLevel source)
- {
- return (byte)source;
- }
-
- ///
- /// Gets the power level description.
- ///
- ///
- /// The power level description.
- public static string GetDescription(this PowerLevel source)
- {
- return lookupTable[source];
- }
-
- ///
- /// Gets the entry associated to the given value.
- ///
- ///
- /// Value of the to retrieve.
- /// The entry associated to the given value, PowerLevel.LEVEL.UNKNOWN
if the could not be found in the list.
- public static PowerLevel Get(this PowerLevel dumb, byte value)
- {
- var values = Enum.GetValues(typeof(PowerLevel)).OfType();
-
- if (values.Cast().Contains(value))
- return (PowerLevel)value;
-
- return PowerLevel.LEVEL_UNKNOWN;
- }
-
- public static string ToDisplayString(this PowerLevel source)
- {
- return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source), lookupTable[source]);
- }
- }
-
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different power levels. The power level indicates the output power value of a
+ /// radio when transmitting data.
+ ///
+ public enum PowerLevel : byte
+ {
+ // Enumeration entries.
+ LEVEL_LOWEST = 0x00,
+ LEVEL_LOW = 0x01,
+ LEVEL_MEDIUM = 0x02,
+ LEVEL_HIGH = 0x03,
+ LEVEL_HIGHEST = 0x04,
+ LEVEL_UNKNOWN = 0xFF
+ }
+
+ public static class PowerLevelExtensions
+ {
+ private static IDictionary lookupTable = new Dictionary();
+
+ static PowerLevelExtensions()
+ {
+ lookupTable.Add(PowerLevel.LEVEL_LOWEST, "Lowest");
+ lookupTable.Add(PowerLevel.LEVEL_LOW, "Low");
+ lookupTable.Add(PowerLevel.LEVEL_MEDIUM, "Medium");
+ lookupTable.Add(PowerLevel.LEVEL_HIGH, "High");
+ lookupTable.Add(PowerLevel.LEVEL_HIGHEST, "Highest");
+ lookupTable.Add(PowerLevel.LEVEL_UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Gets the power level value.
+ ///
+ ///
+ /// The power level value.
+ public static byte GetValue(this PowerLevel source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the power level description.
+ ///
+ ///
+ /// The power level description.
+ public static string GetDescription(this PowerLevel source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the entry associated to the given value.
+ ///
+ ///
+ /// Value of the to retrieve.
+ /// The entry associated to the given value,
+ /// if the could not be
+ /// found in the list.
+ public static PowerLevel Get(this PowerLevel source, byte value)
+ {
+ var values = Enum.GetValues(typeof(PowerLevel)).OfType();
+
+ if (values.Cast().Contains(value))
+ return (PowerLevel)value;
+
+ return PowerLevel.LEVEL_UNKNOWN;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this PowerLevel source)
+ {
+ return string.Format("{0}: {1}", HexUtils.ByteToHexString((byte)source), lookupTable[source]);
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/Range.cs b/XBeeLibrary.Core/Models/Range.cs
new file mode 100644
index 0000000..1002dc3
--- /dev/null
+++ b/XBeeLibrary.Core/Models/Range.cs
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents the range of values valid for an XBee setting.
+ ///
+ public class Range
+ {
+ ///
+ /// Class constructor. Instantiates a new object with the provided parameters.
+ ///
+ /// Minimum allowed value of the range.
+ /// Maximum allowed value of the range.
+ public Range(string rangeMin, string rangeMax)
+ {
+ RangeMin = rangeMin;
+ RangeMax = rangeMax;
+ }
+
+ // Properties.
+ ///
+ /// Minimum allowed value of the range.
+ ///
+ public string RangeMin { get; set; }
+
+ ///
+ /// Maximum allowed value of the range.
+ ///
+ public string RangeMax { get; set; }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/RemoteATCommandOptions.cs b/XBeeLibrary.Core/Models/RemoteATCommandOptions.cs
new file mode 100644
index 0000000..dc03cd4
--- /dev/null
+++ b/XBeeLibrary.Core/Models/RemoteATCommandOptions.cs
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class lists all the possible options that can be set while transmitting a remote AT Command.
+ ///
+ [Flags]
+ public enum RemoteATCommandOptions : byte
+ {
+ ///
+ /// No special transmit options.
+ ///
+ OPTION_NONE = 0x00,
+
+ ///
+ /// Disables ACK.
+ ///
+ OPTION_DISABLE_ACK = 0x01,
+
+ ///
+ /// Applies changes in the remote device.
+ ///
+ /// If this option is not set, AC command must be sent before changes will take effect.
+ OPTION_APPLY_CHANGES = 0x02,
+
+ ///
+ /// Uses the extended transmission timeout.
+ ///
+ /// Setting the extended timeout bit causes the stack to set the extended transmission timeout
+ /// for the destination address.
+ OPTION_EXTENDED_TIMEOUT = 0x40
+ }
+}
diff --git a/XBeeLibrary.Core/Models/SMSMessage.cs b/XBeeLibrary.Core/Models/SMSMessage.cs
new file mode 100644
index 0000000..6e373d1
--- /dev/null
+++ b/XBeeLibrary.Core/Models/SMSMessage.cs
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Text.RegularExpressions;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an SMS message containing the phone number that sent the message and
+ /// the content (data) of the message.
+ ///
+ /// This class is used within the library to read SMS messages sent to Cellular devices.
+ public class SMSMessage
+ {
+ // Constants.
+ private const string PHONE_NUMBER_PATTERN = "^\\+?\\d+$";
+
+ ///
+ /// Class constructor. Instantiates a new object of type with the given
+ /// parameters.
+ ///
+ /// The phone number that sent the message.
+ /// String containing the message text.
+ /// If is invalid.
+ /// If == null
+ /// or if == null.
+ public SMSMessage(string phoneNumber, string data)
+ {
+ if (PhoneNumber == null)
+ throw new ArgumentNullException("Phone number cannot be null.");
+ if (Data == null)
+ throw new ArgumentNullException("Data cannot be null.");
+ if (!Regex.IsMatch(PhoneNumber, PHONE_NUMBER_PATTERN))
+ throw new ArgumentException("Invalid phone number.");
+
+ PhoneNumber = phoneNumber;
+ Data = data;
+ }
+
+ // Properties.
+ ///
+ /// The phone number that sent the message.
+ ///
+ public string PhoneNumber { get; private set; }
+
+ ///
+ /// A string containing the data of the message.
+ ///
+ public string Data { get; private set; }
+ }
+}
diff --git a/XBeeLibrary/Models/SpecialByte.cs b/XBeeLibrary.Core/Models/SpecialByte.cs
similarity index 55%
rename from XBeeLibrary/Models/SpecialByte.cs
rename to XBeeLibrary.Core/Models/SpecialByte.cs
index f1b5f1d..4024ba0 100644
--- a/XBeeLibrary/Models/SpecialByte.cs
+++ b/XBeeLibrary.Core/Models/SpecialByte.cs
@@ -1,68 +1,86 @@
-using System;
-using System.Linq;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates all the special bytes of the XBee protocol that must be escaped when working on API 2 mode.
- ///
- public enum SpecialByte : byte
- {
-
- // Enumeration elements
- ESCAPE_BYTE = 0x7D,
- HEADER_BYTE = 0x7E,
- XON_BYTE = 0x11,
- XOFF_BYTE = 0x13
- }
-
- public static class SpecialByteExtensions
- {
- ///
- /// Gest the special byte value.
- ///
- ///
- /// The special byte value.
- public static byte GetValue(this SpecialByte source)
- {
- return (byte)source;
- }
-
- ///
- /// Gets the entry associated with the given value.
- ///
- ///
- /// Value of the to retrieve.
- /// associated to the given value, null if it does not exist in the list.
- public static SpecialByte Get(this SpecialByte dumb, byte value)
- {
- var values = Enum.GetValues(typeof(SpecialByte)).OfType();
-
- if (values.Cast().Contains(value))
- return (SpecialByte)value;
-
- return 0;
- }
-
- ///
- /// Escapes the byte by performing a XOR operation with 0x20
value.
- ///
- ///
- /// Escaped byte value.
- public static byte EscapeByte(this SpecialByte source)
- {
- return (byte)(((byte)source) ^ 0x20);
- }
-
- ///
- /// Checks whether the given byte is special or not.
- ///
- ///
- /// Byte to check.
- /// true if given byte is special, false otherwise.
- public static bool IsSpecialByte(this SpecialByte dumb, byte byteToCheck)
- {
- return dumb.Get(byteToCheck) != null;
- }
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Linq;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates all the special bytes of the XBee protocol that must be escaped when working on
+ /// API 2 mode.
+ ///
+ public enum SpecialByte : byte
+ {
+ // Enumeration entries.
+ ESCAPE_BYTE = 0x7D,
+ HEADER_BYTE = 0x7E,
+ XON_BYTE = 0x11,
+ XOFF_BYTE = 0x13
+ }
+
+ public static class SpecialByteExtensions
+ {
+ ///
+ /// Gest the special byte value.
+ ///
+ ///
+ /// The special byte value.
+ public static byte GetValue(this SpecialByte source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the entry associated with the given value.
+ ///
+ ///
+ /// Value of the to retrieve.
+ /// associated to the given value, 0 if it does not
+ /// exist in the list.
+ public static SpecialByte Get(this SpecialByte dumb, byte value)
+ {
+ var values = Enum.GetValues(typeof(SpecialByte)).OfType();
+
+ if (values.Cast().Contains(value))
+ return (SpecialByte)value;
+
+ return 0;
+ }
+
+ ///
+ /// Escapes the byte by performing a XOR operation with 0x20
value.
+ ///
+ ///
+ /// Escaped byte value.
+ public static byte EscapeByte(this SpecialByte source)
+ {
+ return (byte)(((byte)source) ^ 0x20);
+ }
+
+ ///
+ /// Checks whether the given byte is special or not.
+ ///
+ ///
+ /// Byte to check.
+ /// true if given byte is special, false otherwise.
+ public static bool IsSpecialByte(this SpecialByte source, byte byteToCheck)
+ {
+ return source.Get(byteToCheck) != 0;
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/SrpError.cs b/XBeeLibrary.Core/Models/SrpError.cs
new file mode 100644
index 0000000..4290d26
--- /dev/null
+++ b/XBeeLibrary.Core/Models/SrpError.cs
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This enumeration lists all the available errors of the SRP authentication.
+ ///
+ public enum SrpError : byte
+ {
+ // Enumeration entries.
+ UNABLE_OFFER_B = 0x80,
+ INCORRECT_PAYLOAD_LENGTH = 0x81,
+ BAD_PROOF_KEY = 0x82,
+ RESOURCE_ALLOCATION_ERROR = 0x83,
+ NOT_CORRECT_SEQUENCE = 0x84,
+ UNKNOWN = 0xFF
+ }
+
+ public static class SrpErrorExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static SrpErrorExtensions()
+ {
+ lookupTable.Add(SrpError.UNABLE_OFFER_B, "Unable to offer B (cryptographic error with content, usually due to A mod N == 0)");
+ lookupTable.Add(SrpError.INCORRECT_PAYLOAD_LENGTH, "Incorrect payload length");
+ lookupTable.Add(SrpError.BAD_PROOF_KEY, "Bad proof of key");
+ lookupTable.Add(SrpError.RESOURCE_ALLOCATION_ERROR, "Resource allocation error");
+ lookupTable.Add(SrpError.NOT_CORRECT_SEQUENCE, "Request contained step not in correct sequence");
+ lookupTable.Add(SrpError.UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Gets the associated with the specified ID .
+ ///
+ ///
+ /// ID value to retrieve .
+ /// The for the specified ID ,
+ /// if it does not exist.
+ public static SrpError Get(this SrpError source, byte value)
+ {
+ var values = Enum.GetValues(typeof(SrpError)).OfType();
+
+ if (values.Cast().Contains(value))
+ return (SrpError)value;
+
+ return SrpError.UNKNOWN;
+ }
+
+ ///
+ /// Gets the SRP error value.
+ ///
+ ///
+ /// The SRP error value.
+ public static byte GetValue(this SrpError source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the SRP error name.
+ ///
+ ///
+ /// The SRP error name.
+ public static string GetName(this SrpError source)
+ {
+ return lookupTable.ContainsKey(source) ? lookupTable[source] : source.ToString();
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this SrpError source)
+ {
+ return string.Format("({0}) {1}", HexUtils.ByteArrayToHexString(ByteUtils.IntToByteArray((byte)source)), GetName(source));
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/SrpPhase.cs b/XBeeLibrary.Core/Models/SrpPhase.cs
new file mode 100644
index 0000000..46f0f17
--- /dev/null
+++ b/XBeeLibrary.Core/Models/SrpPhase.cs
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This enumeration lists all the available phases of the SRP authentication.
+ ///
+ public enum SrpPhase : byte
+ {
+ // Enumeration entries.
+ PHASE_1 = 0x01,
+ PHASE_2 = 0x02,
+ PHASE_3 = 0x03,
+ PHASE_4 = 0x04,
+ UNKNOWN = 0xFF
+ }
+
+ public static class SrpPhaseExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static SrpPhaseExtensions()
+ {
+ lookupTable.Add(SrpPhase.PHASE_1, "Phase 1");
+ lookupTable.Add(SrpPhase.PHASE_2, "Phase 2");
+ lookupTable.Add(SrpPhase.PHASE_3, "Phase 3");
+ lookupTable.Add(SrpPhase.PHASE_4, "Phase 4");
+ lookupTable.Add(SrpPhase.UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Gets the associated with the specified ID .
+ ///
+ ///
+ /// ID value to retrieve .
+ /// The for the specified ID ,
+ /// if it does not exist.
+ public static SrpPhase Get(this SrpPhase source, byte value)
+ {
+ var values = Enum.GetValues(typeof(SrpPhase)).OfType();
+
+ if (values.Cast().Contains(value))
+ return (SrpPhase)value;
+
+ return SrpPhase.UNKNOWN;
+ }
+
+ ///
+ /// Gets the SRP phase value.
+ ///
+ ///
+ /// The SRP phase value.
+ public static byte GetValue(this SrpPhase source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the SRP phase name.
+ ///
+ ///
+ /// The SRP phase name.
+ public static string GetName(this SrpPhase source)
+ {
+ return lookupTable.ContainsKey(source) ? lookupTable[source] : source.ToString();
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this SrpPhase source)
+ {
+ return string.Format("({0}) {1}", HexUtils.ByteArrayToHexString(ByteUtils.IntToByteArray((byte)source)), GetName(source));
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/UserDataRelayMessage.cs b/XBeeLibrary.Core/Models/UserDataRelayMessage.cs
new file mode 100644
index 0000000..92cce05
--- /dev/null
+++ b/XBeeLibrary.Core/Models/UserDataRelayMessage.cs
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents a User Data Relay message containing the source interface from which the
+ /// message was sent and the data.
+ ///
+ public class UserDataRelayMessage
+ {
+ ///
+ /// Instantiates a new object with the given parameters.
+ ///
+ /// Source interface.
+ /// Data.
+ /// If the source interface is unknown.
+ public UserDataRelayMessage(XBeeLocalInterface sourceInterface, byte[] data)
+ {
+ if (sourceInterface == XBeeLocalInterface.UNKNOWN)
+ throw new ArgumentException("Source interface cannot be unknown.");
+
+ SourceInterface = sourceInterface;
+ Data = data;
+ }
+
+ // Properties.
+ ///
+ /// The source interface of the User Data Relay message.
+ ///
+ public XBeeLocalInterface SourceInterface { get; private set; }
+
+ ///
+ /// The data contained in the User Data Relay message.
+ ///
+ public byte[] Data { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/XBee16BitAddress.cs b/XBeeLibrary.Core/Models/XBee16BitAddress.cs
new file mode 100644
index 0000000..02a50bd
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBee16BitAddress.cs
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Linq;
+using System.Text.RegularExpressions;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents a 16-bit network address.
+ ///
+ /// This address is only applicable for:
+ ///
+ /// - 802.15.4
+ /// - ZigBee
+ /// - ZNet 2.5
+ /// - XTend (Legacy)
+ ///
+ /// Each device has its own 16-bit address which is unique in the network. It is automatically
+ /// assigned when the radio joins the network for ZigBee and ZNet 2.5, and manually configured in
+ /// 802.15.4 radios. DigiMesh and Point-to-Multipoint protocols don't support 16-bit addressing.
+ public sealed class XBee16BitAddress : IEquatable
+ {
+ // Constants.
+ ///
+ /// Pattern for the 16-bit address string.
+ ///
+ public static readonly Regex XBEE_16_BIT_ADDRESS_PATTERN = new Regex("(0[xX])?[0-9a-fA-F]{1,4}");
+
+ ///
+ /// 16-bit address reserved for the coordinator (value: 0000).
+ ///
+ public static readonly XBee16BitAddress COORDINATOR_ADDRESS = new XBee16BitAddress("0000");
+
+ ///
+ /// 16-bit broadcast address (value: FFFF).
+ ///
+ public static readonly XBee16BitAddress BROADCAST_ADDRESS = new XBee16BitAddress("FFFF");
+
+ ///
+ /// 16-bit unknown address (value: FFFE).
+ ///
+ public static readonly XBee16BitAddress UNKNOWN_ADDRESS = new XBee16BitAddress("FFFE");
+
+ private const int HASH_SEED = 23;
+
+ // Variables
+ private readonly byte[] address;
+
+ ///
+ /// Initializes a new instance of class .
+ ///
+ /// High significant byte of the address.
+ /// Low significant byte of the address.
+ /// If ]]> 255
+ /// or if 0
+ /// or if ]]> 255
+ /// or if 0.
+ public XBee16BitAddress(byte hsb, byte lsb)
+ {
+ if (hsb < 0 || hsb > 255)
+ throw new ArgumentOutOfRangeException("HSB must be between 0 and 255.");
+ if (lsb < 0 || lsb > 255)
+ throw new ArgumentOutOfRangeException("LSB must be between 0 and 255.");
+
+ address = new byte[2];
+ address[0] = hsb;
+ address[1] = lsb;
+ }
+
+ ///
+ /// Initializes a new instance of class .
+ ///
+ /// The 16-bit address as byte array.
+ /// If == null.
+ /// If Length of != 2.
+ public XBee16BitAddress(byte[] address)
+ {
+ if (address == null)
+ throw new ArgumentNullException("Address cannot be null.");
+ if (address.Length < 1 || address.Length > 2)
+ throw new ArgumentOutOfRangeException("Address must have between 1 and 2 bytes.");
+
+ // Check array size.
+ this.address = new byte[2];
+ int diff = this.address.Length - address.Length;
+ for (int i = 0; i < diff; i++)
+ this.address[i] = 0;
+ for (int i = diff; i < this.address.Length; i++)
+ this.address[i] = address[i - diff];
+ }
+
+ ///
+ /// Initializes a new instance of class .
+ ///
+ /// The string must be the hexadecimal representation of a 16-bit address.
+ /// A string containing the 16-bit address.
+ /// If == null.
+ /// If Length of is
+ /// lower than 1.
+ /// If contains non-hexadecimal
+ /// characters or if it is longer than 2 bytes.
+ public XBee16BitAddress(string address)
+ {
+ if (address == null)
+ throw new ArgumentNullException("Address cannot be null.");
+ if (address.Length < 1)
+ throw new ArgumentOutOfRangeException("Address must contain at least 1 character.");
+ if (!XBEE_16_BIT_ADDRESS_PATTERN.IsMatch(address))
+ throw new FormatException("Address must follow this pattern: (0x)XXXX.");
+
+ // Convert the string into a byte array.
+ byte[] byteAddress = HexUtils.HexStringToByteArray(address);
+ // Check array size.
+ this.address = new byte[2];
+ int diff = this.address.Length - byteAddress.Length;
+ for (int i = 0; i < diff; i++)
+ this.address[i] = 0;
+ for (int i = diff; i < this.address.Length; i++)
+ this.address[i] = byteAddress[i - diff];
+ }
+
+ ///
+ /// Gets the address high significant byte.
+ ///
+ public int Hsb
+ {
+ get
+ {
+ return address[0];
+ }
+ }
+
+ ///
+ /// Gets the address low significant byte.
+ ///
+ public int Lsb
+ {
+ get
+ {
+ return address[1];
+ }
+ }
+
+ ///
+ /// Gets the 16-bit address value in byte array format.
+ ///
+ public byte[] Value
+ {
+ get
+ {
+ return (byte[])address.Clone();
+ }
+ }
+
+ ///
+ /// Returns whether this object is equal to the given one.
+ ///
+ /// The object to compare if it is equal to this one.
+ /// true if this object is equal to the given one, false
+ /// otherwise.
+ public override bool Equals(object obj)
+ {
+ XBee16BitAddress other = obj as XBee16BitAddress;
+ return other != null && Equals(other);
+ }
+
+ ///
+ /// Returns whether this is equal to the given one.
+ ///
+ /// The to compare if it is equal
+ /// to this one.
+ /// true if this is equal to the given
+ /// one, false otherwise.
+ public bool Equals(XBee16BitAddress other)
+ {
+ return other != null && Enumerable.SequenceEqual(other.Value, Value);
+ }
+
+ ///
+ /// Returns the Hash code of this object.
+ ///
+ /// The Hash code of this object.
+ public override int GetHashCode()
+ {
+ int hash = HASH_SEED;
+ foreach (byte b in Value)
+ hash = hash * (hash + b);
+ return hash;
+ }
+
+ ///
+ /// Returns a string representation of this object.
+ ///
+ /// A string representation of this object.
+ public override string ToString()
+ {
+ return HexUtils.ByteArrayToHexString(address);
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/XBee64BitAddress.cs b/XBeeLibrary.Core/Models/XBee64BitAddress.cs
new file mode 100644
index 0000000..ebc35b1
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBee64BitAddress.cs
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents a 64-bit address (also known as MAC address).
+ ///
+ /// The 64-bit address is a unique device address assigned during manufacturing. This
+ /// address is unique to each physical device.
+ public sealed class XBee64BitAddress : IEquatable
+ {
+ // Constants.
+ private const string DEVICE_ID_SEPARATOR = "-";
+ private const string DEVICE_ID_MAC_SEPARATOR = "FF";
+
+ private const int HASH_SEED = 23;
+
+ ///
+ /// Pattern for the 64-bit address string.
+ ///
+ public static readonly Regex XBEE_64_BIT_ADDRESS_PATTERN = new Regex("(0[xX])?[0-9a-fA-F]{1,16}");
+
+ ///
+ /// 64-bit address reserved for the coordinator (value: 0000000000000000).
+ ///
+ public static readonly XBee64BitAddress COORDINATOR_ADDRESS = new XBee64BitAddress("0000");
+
+ ///
+ /// 64-bit broadcast address (value: 000000000000FFFF).
+ ///
+ public static readonly XBee64BitAddress BROADCAST_ADDRESS = new XBee64BitAddress("FFFF");
+
+ ///
+ /// 64-bit unknown address (value: 000000000000FFFE).
+ ///
+ public static readonly XBee64BitAddress UNKNOWN_ADDRESS = new XBee64BitAddress("FFFE");
+
+ // Variables
+ private byte[] address;
+
+ ///
+ /// Initializes a new instance of class .
+ ///
+ /// The 64-bit address as byte array.
+ /// If == null.
+ /// If the Length of is
+ /// not 8.
+ public XBee64BitAddress(byte[] address)
+ {
+ if (address == null)
+ throw new ArgumentNullException("Address cannot be null.");
+ if (address.Length < 1 || address.Length > 8)
+ throw new ArgumentOutOfRangeException("Address must have between 1 abd 8 bytes.");
+
+ this.address = new byte[8];
+ int diff = this.address.Length - address.Length;
+ for (int i = 0; i < diff; i++)
+ this.address[i] = 0;
+ for (int i = diff; i < this.address.Length; i++)
+ this.address[i] = address[i - diff];
+ }
+
+ ///
+ /// Initializes a new instance of class .
+ ///
+ /// The string must be the hexadecimal representation of a 64-bit address.
+ /// A string containing the 64-bit address.
+ /// If == null.
+ /// If Length of is
+ /// lower than 1.
+ /// If contains non-hexadecimal
+ /// characters or if it is longer than 8 bytes.
+ public XBee64BitAddress(string address)
+ {
+ if (address == null)
+ throw new ArgumentNullException("Address cannot be null.");
+ if (address.Length < 1)
+ throw new ArgumentOutOfRangeException("Address must contain at least 1 character.");
+ if (!XBEE_64_BIT_ADDRESS_PATTERN.IsMatch(address))
+ throw new FormatException("Address must follow this pattern: (0x)0013A20040XXXXXX.");
+
+ byte[] byteAddress = HexUtils.HexStringToByteArray(address);
+ this.address = new byte[8];
+ int diff = this.address.Length - byteAddress.Length;
+ for (int i = 0; i < diff; i++)
+ this.address[i] = 0;
+ for (int i = diff; i < this.address.Length; i++)
+ this.address[i] = byteAddress[i - diff];
+ }
+
+ ///
+ /// Initializes a new instance of class with the given bytes being
+ /// the more significant byte and the less significant byte.
+ ///
+ /// XBee 64-bit address bit 0.
+ /// XBee 64-bit address bit 1.
+ /// XBee 64-bit address bit 2.
+ /// XBee 64-bit address bit 3.
+ /// XBee 64-bit address bit 4.
+ /// XBee 64-bit address bit 5.
+ /// XBee 64-bit address bit 6.
+ /// XBee 64-bit address bit 7.
+ ///
+ /// If ]]> 255 or if 0
+ /// or if ]]> 255 or if 0
+ /// or if ]]> 255 or if 0
+ /// or if ]]> 255 or if 0
+ /// or if ]]> 255 or if 0
+ /// or if ]]> 255 or if 0
+ /// or if ]]> 255 or if 0
+ /// or if ]]> 255 or if 0
+ ///
+ public XBee64BitAddress(int b0, int b1, int b2, int b3, int b4, int b5, int b6, int b7)
+ {
+ if (b0 < 0 || b0 > 255)
+ throw new ArgumentOutOfRangeException("B0 must be between 0 and 255.");
+ if (b1 < 0 || b1 > 255)
+ throw new ArgumentOutOfRangeException("B1 must be between 0 and 255.");
+ if (b2 < 0 || b2 > 255)
+ throw new ArgumentOutOfRangeException("B2 must be between 0 and 255.");
+ if (b3 < 0 || b3 > 255)
+ throw new ArgumentOutOfRangeException("B3 must be between 0 and 255.");
+ if (b4 < 0 || b4 > 255)
+ throw new ArgumentOutOfRangeException("B4 must be between 0 and 255.");
+ if (b5 < 0 || b5 > 255)
+ throw new ArgumentOutOfRangeException("B5 must be between 0 and 255.");
+ if (b6 < 0 || b6 > 255)
+ throw new ArgumentOutOfRangeException("B6 must be between 0 and 255.");
+ if (b7 < 0 || b7 > 255)
+ throw new ArgumentOutOfRangeException("B7 must be between 0 and 255.");
+
+ address = new byte[8];
+ address[0] = (byte)b0;
+ address[1] = (byte)b1;
+ address[2] = (byte)b2;
+ address[3] = (byte)b3;
+ address[4] = (byte)b4;
+ address[5] = (byte)b5;
+ address[6] = (byte)b6;
+ address[7] = (byte)b7;
+ }
+
+ ///
+ /// The XBee 64-bit address value as byte array.
+ ///
+ public byte[] Value
+ {
+ get
+ {
+ return (byte[])address.Clone();
+ }
+ }
+
+ ///
+ /// Generates the Device ID corresponding to this to be used in Device Cloud.
+ ///
+ /// Device ID corresponding to this address.
+ public string GenerateDeviceID()
+ {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 2; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ sb.Append(HexUtils.ByteArrayToHexString(new byte[] { 0 }));
+ sb.Append(DEVICE_ID_SEPARATOR);
+ }
+ // Here we should have "00000000-00000000-"
+ // Append first three bytes of the MAC Address, discard first 2.
+ sb.Append(HexUtils.ByteArrayToHexString(new byte[] { address[2], address[3], address[4] }));
+ sb.Append(DEVICE_ID_MAC_SEPARATOR);
+ sb.Append(DEVICE_ID_SEPARATOR);
+ sb.Append(DEVICE_ID_MAC_SEPARATOR);
+ // Here we should have "00000000-00000000-XXXXXXFF-FF"
+ // Append second three bytes of the MAC Address.
+ sb.Append(HexUtils.ByteArrayToHexString(new byte[] { address[5], address[6], address[7] }));
+ return sb.ToString();
+ }
+
+ ///
+ /// Returns whether this object is equal to the given one.
+ ///
+ /// The object to compare if it is equal to this one.
+ /// true if this object is equal to the given one, false
+ /// otherwise.
+ public override bool Equals(object obj)
+ {
+ XBee64BitAddress other = obj as XBee64BitAddress;
+ return other != null && Equals(other);
+ }
+
+ ///
+ /// Returns whether this is equal to the given one.
+ ///
+ /// The to compare if it is equal
+ /// to this one.
+ /// true if this is equal to the given
+ /// one, false otherwise.
+ public bool Equals(XBee64BitAddress other)
+ {
+ return other != null && Enumerable.SequenceEqual(other.Value, Value);
+ }
+
+ ///
+ /// Returns the Hash code of this object.
+ ///
+ /// The Hash code of this object.
+ public override int GetHashCode()
+ {
+ int hash = HASH_SEED;
+
+ foreach (byte b in Value)
+ hash = hash * (hash + b);
+
+ return hash;
+ }
+
+ ///
+ /// Returns a string representation of this object.
+ ///
+ /// A string representation of this object.
+ public override string ToString()
+ {
+ return HexUtils.ByteArrayToHexString(address);
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/XBeeCategory.cs b/XBeeLibrary.Core/Models/XBeeCategory.cs
new file mode 100644
index 0000000..b7dee88
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBeeCategory.cs
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an XBee category of settings.
+ ///
+ public class XBeeCategory : ICloneable
+ {
+ ///
+ /// Class constructor. Instantiates a new with the provided parameters.
+ ///
+ /// Name of the category.
+ /// Description of the category.
+ /// Parent category.
+ /// XBee firmware the category belongs to.
+ ///
+ public XBeeCategory(string name, string description, XBeeCategory parentCategory, XBeeFirmware ownerFirmware)
+ {
+ Name = name;
+ Description = description;
+ ParentCategory = parentCategory;
+ OwnerFirmware = ownerFirmware;
+ }
+
+ // Properties
+ ///
+ /// Name of the category.
+ ///
+ public string Name { get; private set; }
+
+ ///
+ /// Description of the category.
+ ///
+ public string Description { get; private set; }
+
+ ///
+ /// Parent category.
+ ///
+ public XBeeCategory ParentCategory { get; private set; }
+
+ ///
+ /// XBee firmware the category belongs to.
+ ///
+ public XBeeFirmware OwnerFirmware { get; set; }
+
+ ///
+ /// List of settings contained in the category.
+ ///
+ public List Settings { get; set; } = new List();
+
+ ///
+ /// List of sub-categories contained in the category.
+ ///
+ public List Categories { get; set; } = new List();
+
+ ///
+ /// Returns the setting corresponding to the given name from the list of settings.
+ ///
+ /// The name of the setting to retrieve.
+ /// The setting corresponding to the given name, null if it has not been found.
+ public AbstractXBeeSetting GetSetting(string name)
+ {
+ foreach (AbstractXBeeSetting setting in Settings)
+ {
+ if (setting.Name.Equals(name))
+ return setting;
+ }
+ return null;
+ }
+
+ ///
+ /// Creates a shallow copy of the XBeeCategory.
+ ///
+ /// The copy of the XBeeCategory
+ public object Clone()
+ {
+ return MemberwiseClone() as XBeeCategory;
+ }
+
+ ///
+ /// Clones and returns the XBee category object.
+ ///
+ /// The parent category where the cloned category should be placed.
+ /// The owner firmware of the cloned category.
+ /// The cloned XBee category object.
+ public XBeeCategory CloneCategory(XBeeCategory parentCategory, XBeeFirmware ownerFirmware)
+ {
+ XBeeCategory clonedCategory = (XBeeCategory)Clone();
+ clonedCategory.ParentCategory = parentCategory;
+ clonedCategory.OwnerFirmware = ownerFirmware;
+
+ // Clone the settings and add them to the cloned category.
+ List clonedSettings = new List();
+ foreach (AbstractXBeeSetting setting in Settings)
+ clonedSettings.Add(setting.CloneSetting(clonedCategory, ownerFirmware));
+ clonedCategory.Settings = clonedSettings;
+
+ // Clone the categories and add them to the cloned category.
+ List clonedCategories = new List();
+ foreach (XBeeCategory category in Categories)
+ clonedCategories.Add(category.CloneCategory(clonedCategory, ownerFirmware));
+ clonedCategory.Categories = clonedCategories;
+
+ return clonedCategory;
+ }
+ }
+}
diff --git a/XBeeLibrary/Models/XBeeDiscoveryStatus.cs b/XBeeLibrary.Core/Models/XBeeDiscoveryStatus.cs
similarity index 62%
rename from XBeeLibrary/Models/XBeeDiscoveryStatus.cs
rename to XBeeLibrary.Core/Models/XBeeDiscoveryStatus.cs
index b4e5b87..beb7b0e 100644
--- a/XBeeLibrary/Models/XBeeDiscoveryStatus.cs
+++ b/XBeeLibrary.Core/Models/XBeeDiscoveryStatus.cs
@@ -1,75 +1,102 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates all the possible states of the discovery. Discovery status field is part of the indicating the status of the discovery when a packet is sent.
- ///
- ///
- public enum XBeeDiscoveryStatus : byte
- {
- DISCOVERY_STATUS_NO_DISCOVERY_OVERHEAD = 0x00,
- DISCOVERY_STATUS_ADDRESS_DISCOVERY = 0x01,
- DISCOVERY_STATUS_ROUTE_DISCOVERY = 0x02,
- DISCOVERY_STATUS_ADDRESS_AND_ROUTE = 0x03,
- DISCOVERY_STATUS_EXTENDED_TIMEOUT_DISCOVERY = 0x40,
- DISCOVERY_STATUS_UNKNOWN = 0xFF,
- }
-
- public static class XBeeDiscoveryStatusExtensions
- {
- static IDictionary lookupTable = new Dictionary();
-
- static XBeeDiscoveryStatusExtensions()
- {
- lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_NO_DISCOVERY_OVERHEAD, "No discovery overhead");
- lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_ADDRESS_DISCOVERY, "Address discovery");
- lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_ROUTE_DISCOVERY, "Route discovery");
- lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_ADDRESS_AND_ROUTE, "Address and route");
- lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_EXTENDED_TIMEOUT_DISCOVERY, "Extended timeout discovery");
- lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_UNKNOWN, "Unknown");
- }
-
- ///
- /// Gets the discovery status ID.
- ///
- ///
- /// The discovery status ID.
- public static byte GetId(this XBeeDiscoveryStatus source)
- {
- return (byte)source;
- }
-
- ///
- /// Gets the discovery status description.
- ///
- ///
- /// Discovery status description.
- public static string GetDescription(this XBeeDiscoveryStatus source)
- {
- return lookupTable[source];
- }
-
- ///
- /// Gest the associated to the given ID.
- ///
- /// ID of the to retrieve.
- /// The associated with the given ID.
- public static XBeeDiscoveryStatus Get(this XBeeDiscoveryStatus dumb, byte id)
- {
- var values = Enum.GetValues(typeof(XBeeDiscoveryStatus)).OfType();
-
- if (values.Cast().Contains(id))
- return (XBeeDiscoveryStatus)id;
-
- return XBeeDiscoveryStatus.DISCOVERY_STATUS_UNKNOWN;
- }
-
- public static string ToDisplayString(this XBeeDiscoveryStatus source)
- {
- return lookupTable[source];
- }
- }
-}
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates all the possible states of the discovery. Discovery status field is part of the
+ /// indicating the status of the discovery when a
+ /// packet is sent.
+ ///
+ ///
+ public enum XBeeDiscoveryStatus : byte
+ {
+ // Enumeration entries.
+ DISCOVERY_STATUS_NO_DISCOVERY_OVERHEAD = 0x00,
+ DISCOVERY_STATUS_ADDRESS_DISCOVERY = 0x01,
+ DISCOVERY_STATUS_ROUTE_DISCOVERY = 0x02,
+ DISCOVERY_STATUS_ADDRESS_AND_ROUTE = 0x03,
+ DISCOVERY_STATUS_EXTENDED_TIMEOUT_DISCOVERY = 0x40,
+ DISCOVERY_STATUS_UNKNOWN = 0xFF,
+ }
+
+ public static class XBeeDiscoveryStatusExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static XBeeDiscoveryStatusExtensions()
+ {
+ lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_NO_DISCOVERY_OVERHEAD, "No discovery overhead");
+ lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_ADDRESS_DISCOVERY, "Address discovery");
+ lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_ROUTE_DISCOVERY, "Route discovery");
+ lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_ADDRESS_AND_ROUTE, "Address and route");
+ lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_EXTENDED_TIMEOUT_DISCOVERY, "Extended timeout discovery");
+ lookupTable.Add(XBeeDiscoveryStatus.DISCOVERY_STATUS_UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Gets the discovery status ID.
+ ///
+ ///
+ /// The discovery status ID.
+ public static byte GetId(this XBeeDiscoveryStatus source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the discovery status description.
+ ///
+ ///
+ /// Discovery status description.
+ public static string GetDescription(this XBeeDiscoveryStatus source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gest the associated to the given ID.
+ ///
+ ///
+ /// ID of the to retrieve.
+ /// The associated with the given ID,
+ /// if it does not exist.
+ public static XBeeDiscoveryStatus Get(this XBeeDiscoveryStatus source, byte id)
+ {
+ var values = Enum.GetValues(typeof(XBeeDiscoveryStatus)).OfType();
+
+ if (values.Cast().Contains(id))
+ return (XBeeDiscoveryStatus)id;
+
+ return XBeeDiscoveryStatus.DISCOVERY_STATUS_UNKNOWN;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this XBeeDiscoveryStatus source)
+ {
+ return lookupTable[source];
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/XBeeFirmware.cs b/XBeeLibrary.Core/Models/XBeeFirmware.cs
new file mode 100644
index 0000000..d3f4f99
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBeeFirmware.cs
@@ -0,0 +1,682 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using Common.Logging;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using XBeeLibrary.Core.Exceptions;
+using XBeeLibrary.Core.Tools;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an XBee firmware.
+ ///
+ public class XBeeFirmware : ICloneable
+ {
+ // Constants
+ private const string SERIAL_SETTING_BAUD_RATE = "BD";
+ private const string SERIAL_SETTING_STOP_BITS = "SB";
+ private const string SERIAL_SETTING_PARITY = "NB";
+ private const string SERIAL_SETTING_FLOW_CONTROL_CTS = "D7";
+
+ private const int DEFAULT_SERIAL_BAUD_RATE = 9600;
+ private const int DEFAULT_SERIAL_DATA_BITS = 8;
+ private const int DEFAULT_SERIAL_STOP_BITS = 1;
+ private const int DEFAULT_SERIAL_PARITY = 0;
+ private const int DEFAULT_SERIAL_FLOW_CONTROL = 0;
+
+ private const int FLOWCONTROL_RTSCTS_IN = 1;
+ private const int FLOWCONTROL_RTSCTS_OUT = 2;
+
+ public const string EXTENSION_EHX2 = ".ehx2";
+ public const string EXTENSION_EBIN = ".ebin";
+
+ // Variables.
+ private ILog logger;
+
+ ///
+ /// Class constructor. Instantiates a new object with the provided parameters.
+ ///
+ /// XBee product family name.
+ /// XBee product name.
+ /// Hardware version the firmware is compatible with.
+ /// Compatibility number of the XBee firmware.
+ /// XBee firmware version.
+ /// Configuration buffer location of the XBee firmware.
+ /// Flash page size (in bytes) of the XBee firmware.
+ /// CRC buffer length of the XBee firmware.
+ /// XBee function.
+ public XBeeFirmware(string family, string productName, string hardwareVersion,
+ string compatibilityNumber, string firmwareVersion, string configBufferLocation,
+ string flashPageSize, string crcBufferLength, string function)
+ {
+ Family = family;
+ ProductName = productName;
+ HardwareVersion = hardwareVersion;
+ CompatibilityNumber = compatibilityNumber;
+ FirmwareVersion = firmwareVersion;
+ ConfigBufferLocation = configBufferLocation;
+ FlashPageSize = flashPageSize;
+ CrcBufferLength = crcBufferLength;
+ Function = function;
+
+ logger = LogManager.GetLogger();
+ }
+
+ // Properties.
+ ///
+ /// XBee product family name.
+ ///
+ public string Family { get; private set; }
+
+ ///
+ /// XBee product name.
+ ///
+ public string ProductName { get; private set; }
+
+ ///
+ /// Hardware version the firmware is compatible with.
+ ///
+ public string HardwareVersion { get; set; }
+
+ ///
+ /// Compatibility number of the XBee firmware.
+ ///
+ public string CompatibilityNumber { get; private set; }
+
+ ///
+ /// Version of the XBee firmware.
+ ///
+ public string FirmwareVersion { get; private set; }
+
+ ///
+ /// Configuration buffer location of the XBee firmware.
+ ///
+ public string ConfigBufferLocation { get; private set; }
+
+ ///
+ /// Flash page size (in bytes) of the XBee firmware.
+ ///
+ public string FlashPageSize { get; private set; }
+
+ ///
+ /// CRC buffer length of the XBee firmware.
+ ///
+ public string CrcBufferLength { get; private set; }
+
+ ///
+ /// XBee function.
+ ///
+ public string Function { get; private set; }
+
+ ///
+ /// Path where the XML definition file is located.
+ ///
+ public string DefinitionFileLocation { get; private set; }
+
+ ///
+ /// String containing the full content of the XML definition file.
+ ///
+ public string DefinitionFileContent { get; set; }
+
+ ///
+ /// Path where the binary file is located.
+ ///
+ public string BinaryFileLocation { get; set; }
+
+ ///
+ /// Region string identifier of the firmware.
+ ///
+ public string Region { get; set; } = "99";
+
+ ///
+ /// Version of the modem firmware associated to the XBee firmware.
+ ///
+ public string ModemVersion { get; set; }
+
+ ///
+ /// URL where the modem firmware associated to the XBee firmware
+ /// is stored.
+ ///
+ public string ModemUrl { get; set; }
+
+ ///
+ /// Indicates whether the firmware is initialized (categories and settings have been parsed
+ /// and listed) or not.
+ ///
+ public bool Initialized { get; set; } = false;
+
+ ///
+ /// Indicates whether the settings have been read at least 1 time or
+ /// not.
+ ///
+ public bool FirstTimeRead { get; set; } = true;
+
+ ///
+ /// Indicates the index of the current active network (index starts
+ /// at 1).
+ ///
+ public int ActiveNetworkIndex { get; set; } = 1;
+
+ ///
+ /// List of configuration categories of the firmware.
+ ///
+ public List Categories { get; set; } = new List();
+
+ ///
+ /// Dictionary containing the dependencies. The key correspondonds to the AT command of the
+ /// setting that has a dependency. The value is a list of AT commands corresponding to the
+ /// settings that depend on the key one.
+ ///
+ private Dictionary> dependencies = new Dictionary>();
+
+ ///
+ /// Sets the path where the XML definition file of this XBee firmware is located.
+ ///
+ /// The XML definition file path.
+ public void SetDefinitionFilePath(string definitionFileLocation)
+ {
+ DefinitionFileLocation = definitionFileLocation.Replace("\\", "/");
+ BinaryFileLocation = definitionFileLocation.Replace(ParsingUtils.XML_EXTENSION, "").Replace(ParsingUtils.MXI_EXTENSION, "");
+ }
+
+ ///
+ /// Returns the path where the binary file of this XBee firmware is located, including the
+ /// extension of the binary.
+ ///
+ /// The path (with extension) where the binary file of this XBee firmware is located
+ public string GetBinaryFileWithExtensionPath()
+ {
+ if (BinaryFileLocation != null)
+ {
+ FileInfo binaryFile = new FileInfo(BinaryFileLocation + EXTENSION_EBIN);
+ if (!binaryFile.Exists)
+ binaryFile = new FileInfo(BinaryFileLocation + EXTENSION_EHX2);
+
+ if (binaryFile.Exists)
+ return binaryFile.FullName;
+ }
+ return null;
+ }
+
+ ///
+ /// Parses and fills the contents of this XBee firmware.
+ ///
+ public void FillContents()
+ {
+ XMLFirmwareParser.ParseFirmwareContents(this);
+ }
+
+ ///
+ /// Returns whether this object is equal to the given one.
+ ///
+ /// The object to compare if it is equal to this one.
+ /// true if this object is equal to the given one, false
+ /// otherwise.
+ public override bool Equals(object obj)
+ {
+ if (!(obj is XBeeFirmware))
+ return false;
+
+ if (((XBeeFirmware)obj).FirmwareVersion.Equals(FirmwareVersion)
+ && ((XBeeFirmware)obj).HardwareVersion.Equals(HardwareVersion))
+ return true;
+
+ return false;
+ }
+
+ ///
+ /// Returns the Hash code of this object.
+ ///
+ /// The Hash code of this object.
+ public override int GetHashCode()
+ {
+ return HardwareVersion.GetHashCode() + FirmwareVersion.GetHashCode();
+ }
+
+ ///
+ /// Returns a string representation of this object.
+ ///
+ /// A string representation of this object.
+ public override string ToString()
+ {
+ return "[" + FirmwareVersion + "]" + Function;
+ }
+
+ ///
+ /// Returns the list of settings defined in the firmware.
+ ///
+ /// The list of settings defined in the firmware.
+ public List GetAtSettings()
+ {
+ List atSettings = new List();
+ foreach (XBeeCategory category in Categories)
+ AddATSettings(category, atSettings);
+
+ return atSettings;
+ }
+
+ ///
+ /// Returns the list of settings that don't support multiple networks. If the firmware only
+ /// supports 1 network, this method returns the same list as .
+ ///
+ /// The list of settings that don't support multiple networks.
+ public List GetCommonAtSettings()
+ {
+ List atCommonSettings = new List();
+ foreach (XBeeCategory category in Categories)
+ AddCommonATSettings(category, atCommonSettings);
+
+ return atCommonSettings;
+ }
+
+
+ ///
+ /// Returns the list of settings that can be configured for multiple networks.
+ ///
+ /// The list of settings that can be configured for multiple networks.
+ public List GetDualAtSettings()
+ {
+ List atDualSettings = new List();
+ foreach (XBeeCategory category in Categories)
+ AddDualATSettings(category, atDualSettings);
+
+ return atDualSettings;
+ }
+
+ ///
+ /// Returns the total number of settings contained in the XBee firmware.
+ ///
+ /// The total number of setings of the firmware.
+ public int GetATSettingsNumber()
+ {
+ int atSettingsNumber = 0;
+ foreach (XBeeCategory category in Categories)
+ AddATSettingsNumber(category, atSettingsNumber);
+ return atSettingsNumber;
+ }
+
+ ///
+ /// Returns the setting corresponding to the provided in any category
+ /// of the firmware.
+ ///
+ /// The AT command corresponding to the setting to get.
+ /// The setting corresponding to the provided AT command.
+ public AbstractXBeeSetting GetAtSetting(string atCommand)
+ {
+ foreach (XBeeCategory category in Categories)
+ {
+ AbstractXBeeSetting atSetting = GetAtSetting(atCommand, category);
+ if (atSetting != null)
+ return atSetting;
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the XBee value (value stored in the XBee module) of the baud rate setting of the firmware.
+ ///
+ /// The XBee value of the baud rate setting of the firmware.
+ public int GetSerialBaudRate()
+ {
+ AbstractXBeeSetting atSetting = GetAtSetting(SERIAL_SETTING_BAUD_RATE);
+ if (atSetting != null)
+ {
+ // Do not specify the network stack of the BD parameter by the moment (it's a common value).
+ // TODO: [DUAL] When this setting is implemented individually for each network stack, update this code to
+ // specify the network ID from which this parameter should be read.
+ string settingValue = atSetting.GetXBeeValue();
+ if (!ParsingUtils.IsHexadecimal(atSetting.GetXBeeValue()))
+ return DEFAULT_SERIAL_BAUD_RATE;
+
+ switch (ParsingUtils.HexStringToInt(settingValue))
+ {
+ case 0:
+ return 1200;
+ case 1:
+ return 2400;
+ case 2:
+ return 4800;
+ case 3:
+ return 9600;
+ case 4:
+ return 19200;
+ case 5:
+ return 38400;
+ case 6:
+ return 57600;
+ case 7:
+ return 115200;
+ case 8:
+ return 230400;
+ case 9:
+ return 460800;
+ case 10:
+ return 921600;
+ default:
+ return DEFAULT_SERIAL_BAUD_RATE;
+ }
+ }
+ return DEFAULT_SERIAL_BAUD_RATE;
+ }
+
+ ///
+ /// Returns the number of serial data bits.
+ ///
+ /// The number of serial data bits.
+ public int GetSerialDataBits()
+ {
+ return DEFAULT_SERIAL_DATA_BITS;
+ }
+
+ ///
+ /// Returns the XBee value (value stored in the XBee module) of the stop bits setting of the
+ /// firmware.
+ ///
+ /// The XBee value of the stop bits setting of the firmware.
+ public int GetSerialStopBits()
+ {
+ AbstractXBeeSetting atSetting = GetAtSetting(SERIAL_SETTING_STOP_BITS);
+ if (atSetting != null)
+ {
+ // Do not specify the network stack of the SB parameter by the moment (it's a common value).
+ // TODO: [DUAL] When this setting is implemented individually for each network stack, update this code to
+ // specify the network ID from which this parameter should be read.
+ string settingValue = atSetting.GetXBeeValue();
+ if (!ParsingUtils.IsInteger(atSetting.GetXBeeValue()))
+ return DEFAULT_SERIAL_STOP_BITS;
+
+ switch (int.Parse(settingValue))
+ {
+ case 0:
+ return 1;
+ case 1:
+ return 2;
+ default:
+ return DEFAULT_SERIAL_STOP_BITS;
+ }
+ }
+ return DEFAULT_SERIAL_STOP_BITS;
+ }
+
+ ///
+ /// Returns the XBee value (value stored in the XBee module) of the serial parity setting of the firmware.
+ ///
+ /// The XBee value of the serial parity setting of the firmware.
+ public int GetSerialParity()
+ {
+ AbstractXBeeSetting atSetting = GetAtSetting(SERIAL_SETTING_PARITY);
+ if (atSetting != null)
+ {
+ // Do not specify the network stack of the NB parameter by the moment (it's a common value).
+ // TODO: [DUAL] When this setting is implemented individually for each network stack, update this code to
+ // specify the network ID from which this parameter should be read.
+ string settingValue = atSetting.GetXBeeValue();
+ if (!ParsingUtils.IsInteger(atSetting.GetXBeeValue()))
+ return DEFAULT_SERIAL_PARITY;
+
+ switch (int.Parse(settingValue))
+ {
+ case 0:
+ return 0;
+ case 1:
+ return 2;
+ case 2:
+ return 1;
+ case 3:
+ return 3;
+ case 4:
+ return 4;
+ default:
+ return DEFAULT_SERIAL_PARITY;
+ }
+ }
+ return DEFAULT_SERIAL_PARITY;
+ }
+
+ ///
+ /// Returns whether the XBee firmware has serial interface or not.
+ ///
+ /// true if the firmware has serial interface, false otherwise.
+ public bool HasSerialInterface()
+ {
+ if (GetAtSetting(SERIAL_SETTING_BAUD_RATE) == null)
+ return false;
+
+ return true;
+ }
+
+ ///
+ /// Returns whether this firmware addresses multiple networks or not.
+ ///
+ /// true if the firmware addresses more than 1 network,
+ /// false otherwise.
+ public bool SupportsMultipleNetworks()
+ {
+ // Look in each setting of each category.
+ foreach (XBeeCategory category in Categories)
+ {
+ foreach (AbstractXBeeSetting setting in category.Settings)
+ {
+ if (setting.SupportsMultipleNetworks())
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Retrieves the number of networks addressed by this firmware.
+ ///
+ /// The number of networks addressed by this firmware.
+ public int GetNumberOfNetworks()
+ {
+ int numNetworks = 1;
+ foreach (XBeeCategory category in Categories)
+ {
+ foreach (AbstractXBeeSetting setting in category.Settings)
+ {
+ if (setting.NumNetworks > numNetworks)
+ numNetworks = setting.NumNetworks;
+ }
+ }
+ return numNetworks;
+ }
+
+ ///
+ /// Adds a setting dependency.
+ ///
+ ///
+ /// [XCTUNG-1180] Range may contain a reference to another AT command.
+ ///
+ /// Setting that has a dependency.
+ /// Setting that depends on atCommand.
+ public void AddDependency(string atCommand, string dependsOn)
+ {
+ if (!dependencies.TryGetValue(atCommand, out List deps))
+ deps = new List();
+
+ if (!deps.Contains(dependsOn))
+ {
+ deps.Add(dependsOn);
+ dependencies[atCommand] = deps;
+ }
+ }
+
+ ///
+ /// Gets the dependencies of the given setting.
+ ///
+ /// Setting of which obtain the dependencies.
+ /// List of AT commands that depend on the given one.
+ public List GetDependencies(string atCommand)
+ {
+ if (!dependencies.TryGetValue(atCommand, out List deps))
+ return new List();
+
+ return deps;
+ }
+
+ ///
+ /// Returns a string containing the supported binaries separated by '|' char.
+ ///
+ /// A string containing the supported binaries.
+ public static string GetSupportedBinaries()
+ {
+ return (EXTENSION_EBIN + "|" + EXTENSION_EHX2).Replace(".", "");
+ }
+
+ ///
+ /// Creates a shallow copy of the XBeeFirmware.
+ ///
+ /// The copy of the XBeeFirmware
+ public object Clone()
+ {
+ return MemberwiseClone() as XBeeFirmware;
+ }
+
+ ///
+ /// Clones and returns the XBee firmware object.
+ ///
+ /// The cloned XBee firmware object.
+ public XBeeFirmware CloneFirmware()
+ {
+ // Verify if the firmware needs to fill its contents.
+ if (!Initialized)
+ {
+ try
+ {
+ FillContents();
+ }
+ catch (ParsingException e)
+ {
+ logger.Error(e.Message, e);
+ }
+ }
+
+ XBeeFirmware clonedFirmware = (XBeeFirmware)Clone();
+
+ // Clone the categories and set them to the cloned firmware.
+ List clonedCategories = new List();
+ foreach (XBeeCategory category in Categories)
+ clonedCategories.Add(category.CloneCategory(null, clonedFirmware));
+ clonedFirmware.Categories = clonedCategories;
+
+ return clonedFirmware;
+ }
+
+ ///
+ /// Adds a setting to the list of settings of the firmware.
+ ///
+ /// The configuration category the setting belongs to.
+ /// The setting to add.
+ ///
+ ///
+ private void AddATSettings(XBeeCategory category, List atSettings)
+ {
+ foreach (AbstractXBeeSetting xbeeSetting in category.Settings)
+ atSettings.Add(xbeeSetting);
+
+ foreach (XBeeCategory subCategory in category.Categories)
+ AddATSettings(subCategory, atSettings);
+ }
+
+ ///
+ /// Adds the common settings of the prvided to the given
+ /// list.
+ ///
+ /// The category to look for common settings.
+ /// List of settings where common ones will be added.
+ ///
+ ///
+ private void AddCommonATSettings(XBeeCategory category, List atCommonSettings)
+ {
+ foreach (AbstractXBeeSetting xbeeSetting in category.Settings)
+ {
+ if (!xbeeSetting.SupportsMultipleNetworks())
+ atCommonSettings.Add(xbeeSetting);
+ }
+
+ foreach (XBeeCategory subCategory in category.Categories)
+ AddCommonATSettings(subCategory, atCommonSettings);
+ }
+
+ ///
+ /// Adds the dual settings of the prvided to the given
+ /// list.
+ ///
+ /// The category to look for dual settings.
+ /// List of settings where dual ones will be added.
+ ///
+ ///
+ private void AddDualATSettings(XBeeCategory category, List atDualSettings)
+ {
+ foreach (AbstractXBeeSetting xbeeSetting in category.Settings)
+ {
+ if (xbeeSetting.SupportsMultipleNetworks())
+ atDualSettings.Add(xbeeSetting);
+ }
+
+ foreach (XBeeCategory subCategory in category.Categories)
+ AddDualATSettings(subCategory, atDualSettings);
+ }
+
+ ///
+ /// Adds the number of settings contained in the given to the
+ /// provided value.
+ ///
+ /// The category to get the number of settings that it contains.
+ /// The value to append the number of settings of the category.
+ ///
+ private void AddATSettingsNumber(XBeeCategory category, int atSettingsNumber)
+ {
+ foreach (AbstractXBeeSetting xbeeSetting in category.Settings)
+ atSettingsNumber += 1;
+
+ foreach (XBeeCategory subCategory in category.Categories)
+ AddATSettingsNumber(subCategory, atSettingsNumber);
+ }
+
+ ///
+ /// Returns the setting corresponding to the provided and located
+ /// in the given .
+ ///
+ /// The AT command corresponding to the setting to get.
+ /// The configuration category where the setting should be found.
+ /// The setting corresponding to the provided AT command and category.
+ ///
+ ///
+ private AbstractXBeeSetting GetAtSetting(string atCommand, XBeeCategory category)
+ {
+ foreach (AbstractXBeeSetting xbeeSetting in category.Settings)
+ {
+ if (xbeeSetting.AtCommand != null
+ && xbeeSetting.AtCommand.ToUpper().Equals(atCommand.ToUpper()))
+ return xbeeSetting;
+ }
+
+ foreach (XBeeCategory subCategory in category.Categories)
+ {
+ AbstractXBeeSetting atSetting = GetAtSetting(atCommand, subCategory);
+ if (atSetting != null)
+ return atSetting;
+ }
+ return null;
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/XBeeIMEIAddress.cs b/XBeeLibrary.Core/Models/XBeeIMEIAddress.cs
new file mode 100644
index 0000000..000c6c5
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBeeIMEIAddress.cs
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Text;
+using System.Text.RegularExpressions;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an IMEI address used by cellular devices.
+ ///
+ /// This address is only applicable for:
+ ///
+ /// - Cellular
+ ///
+ public class XBeeIMEIAddress
+ {
+ // Constants.
+ private const string ERROR_IMEI_NULL = "IMEI address cannot be null.";
+ private const string ERROR_IMEI_TOO_LONG = "IMEI address cannot be longer than 8 bytes.";
+ private const string ERROR_IMEI_INVALID = "Invalid IMEI address.";
+
+ private const int HASH_SEED = 23;
+
+ private const string IMEI_PATTERN = "^\\d{0,15}$";
+
+ // Variables.
+ private byte[] address;
+
+ ///
+ /// Class constructor. Instantiates a new object of type with the
+ /// given parameter.
+ ///
+ /// The IMEI address as byte array.
+ /// If == null.
+ /// If ]]> 8.
+ public XBeeIMEIAddress(byte[] address)
+ {
+ if (address == null)
+ throw new ArgumentNullException(ERROR_IMEI_NULL);
+ if (address.Length > 8)
+ throw new ArgumentException(ERROR_IMEI_TOO_LONG);
+
+ GenerateByteAddress(address);
+ }
+
+ ///
+ /// Class constructor. Instantiates a new object of type with the
+ /// given parameter.
+ ///
+ /// The IMEI address as string.
+ /// If == null.
+ /// If does not match the IMEI
+ /// address pattern.
+ public XBeeIMEIAddress(string address)
+ {
+ if (address == null)
+ throw new ArgumentNullException(ERROR_IMEI_NULL);
+
+ if (!Regex.IsMatch(IMEI_PATTERN, address))
+ throw new ArgumentException(ERROR_IMEI_INVALID);
+
+ byte[] byteAddress = HexUtils.HexStringToByteArray(address);
+
+ GenerateByteAddress(byteAddress);
+ }
+
+ // Properties.
+ ///
+ /// Gets the IMEI address value.
+ ///
+ public string Value => HexUtils.ByteArrayToHexString(address).Substring(1);
+
+ ///
+ /// Returns whether this object is equal to the given one.
+ ///
+ /// The object to compare if it is equal to this one.
+ /// true if this object is equal to the given one, false
+ /// otherwise.
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return false;
+ if (!(obj is XBeeIMEIAddress))
+ return false;
+ XBeeIMEIAddress addr = obj as XBeeIMEIAddress;
+ return addr.Value.Equals(Value);
+ }
+
+ ///
+ /// Returns the Hash code of this object.
+ ///
+ /// The Hash code of this object.
+ public override int GetHashCode()
+ {
+ int hash = HASH_SEED;
+ foreach (byte b in Encoding.UTF8.GetBytes(Value))
+ hash = hash * (hash + b);
+ return hash;
+ }
+
+ ///
+ /// Returns a string representation of this object.
+ ///
+ /// A string representation of this object.
+ public override string ToString()
+ {
+ return Value;
+ }
+
+ ///
+ /// Generates and saves the IMEI byte address based on the given byte array.
+ ///
+ /// The byte array used to generate the final IMEI byte address.
+ private void GenerateByteAddress(byte[] byteAddress)
+ {
+ address = new byte[8];
+
+ int diff = 8 - byteAddress.Length;
+ for (int i = 0; i < diff; i++)
+ address[i] = 0;
+ for (int i = diff; i < 8; i++)
+ address[i] = byteAddress[i - diff];
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/XBeeLocalInterface.cs b/XBeeLibrary.Core/Models/XBeeLocalInterface.cs
new file mode 100644
index 0000000..106357b
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBeeLocalInterface.cs
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using XBeeLibrary.Core.Utils;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// Enumerates the different XBee local interfaces used in the Relay API packets.
+ ///
+ public enum XBeeLocalInterface : byte
+ {
+ // Enumeration entries.
+ SERIAL = 0x00,
+ BLUETOOTH = 0x01,
+ MICROPYTHON = 0x02,
+ UNKNOWN = 0xFF
+ }
+
+ public static class XBeeLocalInterfaceExtensions
+ {
+ static IDictionary lookupTable = new Dictionary();
+
+ static XBeeLocalInterfaceExtensions()
+ {
+ lookupTable.Add(XBeeLocalInterface.SERIAL, "Serial port");
+ lookupTable.Add(XBeeLocalInterface.BLUETOOTH, "Bluetooth Low Energy");
+ lookupTable.Add(XBeeLocalInterface.MICROPYTHON, "MicroPython");
+ lookupTable.Add(XBeeLocalInterface.UNKNOWN, "Unknown");
+ }
+
+ ///
+ /// Gets the XBee local interface value.
+ ///
+ ///
+ /// The XBee local interface value.
+ public static byte GetValue(this XBeeLocalInterface source)
+ {
+ return (byte)source;
+ }
+
+ ///
+ /// Gets the XBee local interface description.
+ ///
+ ///
+ /// The XBee local interface description.
+ public static string GetDescription(this XBeeLocalInterface source)
+ {
+ return lookupTable[source];
+ }
+
+ ///
+ /// Gets the associated with the specified ID .
+ ///
+ ///
+ /// ID value to retrieve .
+ /// The for the specified ID ,
+ /// if it does not exist.
+ ///
+ public static XBeeLocalInterface Get(this XBeeLocalInterface source, byte value)
+ {
+ var values = Enum.GetValues(typeof(XBeeLocalInterface)).OfType();
+
+ if (values.Cast().Contains(value))
+ return (XBeeLocalInterface)value;
+
+ return XBeeLocalInterface.UNKNOWN;
+ }
+
+ ///
+ /// Returns the in string format.
+ ///
+ ///
+ /// The in string format.
+ public static string ToDisplayString(this XBeeLocalInterface source)
+ {
+ return HexUtils.ByteToHexString((byte)source) + ": " + lookupTable[source];
+ }
+ }
+}
diff --git a/XBeeLibrary.Core/Models/XBeeMessage.cs b/XBeeLibrary.Core/Models/XBeeMessage.cs
new file mode 100644
index 0000000..014367d
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBeeMessage.cs
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Text;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents an XBee message containing the remote XBee device the message belongs
+ /// to, the content (data) of the message and a flag indicating if the message is a broadcast
+ /// message (was received or is being sent via broadcast).
+ ///
+ /// This class is used within the XBee C# Library to read data sent by remote devices.
+ public class XBeeMessage
+ {
+ ///
+ /// Initializes new instance of class .
+ ///
+ /// The remote XBee device the message belongs to.
+ /// Byte array containing the data of the message.
+ ///
+ public XBeeMessage(RemoteXBeeDevice remoteXBeeDevice, byte[] data)
+ : this(remoteXBeeDevice, data, false) { }
+
+ ///
+ /// Initializes new instance of class .
+ ///
+ /// The remote XBee device the message belongs to.
+ /// Byte array containing the data of the message.
+ /// Indicates if the message was received via broadcast.
+ /// If is null
+ /// or if is null.
+ ///
+ public XBeeMessage(RemoteXBeeDevice remoteXBeeDevice, byte[] data, bool isBroadcast)
+ {
+ Device = remoteXBeeDevice ?? throw new ArgumentNullException("Remote XBee device cannot be null.");
+ Data = data ?? throw new ArgumentNullException("Data cannot be null.");
+ IsBroadcast = isBroadcast;
+ }
+
+ // Properties.
+ ///
+ /// The remote XBee device this message is associated to.
+ ///
+ public RemoteXBeeDevice Device { get; private set; }
+
+ ///
+ /// The data as byte array containing the data of the message.
+ ///
+ public byte[] Data { get; private set; }
+
+ ///
+ /// Gets whether or not the message was received via broadcast.
+ ///
+ public bool IsBroadcast { get; private set; }
+
+ ///
+ /// Gets the data of the message in string format.
+ ///
+ /// The data of the message in string format.
+ public string DataString
+ {
+ get
+ {
+ return Encoding.UTF8.GetString(Data, 0, Data.Length);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary.Core/Models/XBeePacketsQueue.cs b/XBeeLibrary.Core/Models/XBeePacketsQueue.cs
new file mode 100644
index 0000000..c932881
--- /dev/null
+++ b/XBeeLibrary.Core/Models/XBeePacketsQueue.cs
@@ -0,0 +1,647 @@
+/*
+ * Copyright 2019, Digi International Inc.
+ * Copyright 2014, 2015, Sébastien Rault.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading.Tasks;
+using XBeeLibrary.Core.Packet;
+using XBeeLibrary.Core.Packet.Common;
+using XBeeLibrary.Core.Packet.IP;
+using XBeeLibrary.Core.Packet.Raw;
+using XBeeLibrary.Core.Packet.Relay;
+
+namespace XBeeLibrary.Core.Models
+{
+ ///
+ /// This class represents a queue of XBee packets used for sequential packet reading.
+ ///
+ /// The class provides some methods to get specific packet types from different source
+ /// nodes.
+ ///
+ public class XBeePacketsQueue
+ {
+ // Constants.
+ ///
+ /// Default maximum number of packets to store in the queue.
+ ///
+ public const int DEFAULT_MAX_LENGTH = 50;
+
+ // Variables.
+ private LinkedList packetsList;
+
+ ///
+ /// Initializes a new instance of class .
+ ///
+ public XBeePacketsQueue() : this(DEFAULT_MAX_LENGTH) { }
+
+ ///
+ /// Initializes a new instance of class with the specified
+ /// .
+ ///
+ /// Maximum Length of the queue.
+ /// If 1.
+ public XBeePacketsQueue(int maxLength)
+ {
+ if (maxLength < 1)
+ throw new ArgumentException("Queue Length must be greater than 0.");
+
+ MaxSize = maxLength;
+ packetsList = new LinkedList();
+ }
+
+ // Properties.
+ ///
+ /// Gets the maximum size of the XBee packets queue.
+ ///
+ public int MaxSize { get; private set; }
+
+ ///
+ /// Adds the provided packet to the list of packets. If the queue is full
+ /// the first packet will be discarded to add the given one.
+ ///
+ /// The XBee packet to be added to the list.
+ ///
+ public void AddPacket(XBeePacket xbeePacket)
+ {
+ if (packetsList.Count == MaxSize)
+ packetsList.RemoveFirst();
+
+ packetsList.AddLast(xbeePacket);
+ }
+
+ ///
+ /// Clears the list of packets.
+ ///
+ public void ClearQueue()
+ {
+ packetsList.Clear();
+ }
+
+ ///
+ /// Returns the current time in milliseconds since 01/01/1970.
+ ///
+ /// The current time in milliseconds since 01/01/1970.
+ private static long CurrentTimeMillis()
+ {
+ return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds;
+ }
+
+ ///
+ /// Returns the first packet from the queue waiting up to the specified timeout if necessary
+ /// for an XBee packet to become available. Or null if the queue is empty.
+ ///
+ /// The time in milliseconds to wait for an XBee packet to become
+ /// available. 0 to return immediately.
+ /// The first packet from the queue, null if it is empty.
+ ///
+ public XBeePacket GetFirstPacket(int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstPacket(0);
+ // Wait for a timeout or until an XBee packet is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstPacket(0);
+ }
+ return xbeePacket;
+ }
+ else if (packetsList.Count > 0)
+ {
+ var first = packetsList.First.Value;
+ packetsList.RemoveFirst();
+
+ return first;
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first packet from the queue whose 64-bit source address matches the address
+ /// of the provided remote XBee device.
+ ///
+ /// The methods waits up to the specified timeout if necessary for an XBee packet to
+ /// become available. null if the queue is empty or there is not any XBee packet sent by the
+ /// provided remote XBee device.
+ /// The remote XBee device containing the 4-bit address to look
+ /// for in the list of packets.
+ /// The time in milliseconds to wait for an XBee packet from the specified
+ /// remote XBee device to become available. 0 to return immediately.
+ /// The first XBee packet whose 64-bit address matches the address of the provided remote
+ /// XBee device. null if no packets from the specified XBee device are found in the queue.
+ ///
+ ///
+ public XBeePacket GetFirstPacketFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstPacketFrom(remoteXBeeDevice, 0);
+ // Wait for a timeout or until an XBee packet from remoteXBeeDevice is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstPacketFrom(remoteXBeeDevice, 0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (AddressesMatch(xbeePacket, remoteXBeeDevice))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first data packet from the queue waiting up to the specified timeout if necessary
+ /// for an XBee data packet to become available. null if the queue is empty or there is not
+ /// any data packet inside.
+ ///
+ /// The time in milliseconds to wait for an XBee data packet to become
+ /// available. 0 to return immediately.
+ /// The first data packet from the queue, null if it is empty or no data packets
+ /// are contained in the queue.
+ ///
+ public XBeePacket GetFirstDataPacket(int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstDataPacket(0);
+ // Wait for a timeout or until a data XBee packet is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstDataPacket(0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (IsDataPacket(xbeePacket))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first data packet from the queue whose 64-bit source address matches the address
+ /// of the provided remote XBee device.
+ ///
+ /// The methods waits up to the specified timeout if necessary for an XBee data packet to
+ /// become available. null if the queue is empty or there is not any XBee data packet sent
+ /// by the provided remote XBee device.
+ /// The XBee device containing the 64-bit address to look for in
+ /// the list of packets.
+ /// The time in milliseconds to wait for an XBee data packet from the
+ /// specified remote XBee device to become available. 0 to return immediately.
+ /// The first XBee data packet whose its 64-bit address matches the address of the
+ /// provided remote XBee device. null if no data packets from the specified XBee device are
+ /// found in the queue.
+ ///
+ ///
+ public XBeePacket GetFirstDataPacketFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstDataPacketFrom(remoteXBeeDevice, 0);
+ // Wait for a timeout or until an XBee packet from remoteXBeeDevice is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstDataPacketFrom(remoteXBeeDevice, 0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (IsDataPacket(xbeePacket) && AddressesMatch(xbeePacket, remoteXBeeDevice))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first explicit data packet from the queue waiting up to the specified timeout if
+ /// necessary for an XBee explicit data packet to become available. null if the queue is
+ /// empty or there is not any explicit data packet inside.
+ ///
+ /// The time in milliseconds to wait for an XBee explicit data packet to
+ /// become available. 0 to return immediately.
+ /// The first explicit data packet from the queue, null if it is empty or no data
+ /// packets are contained in the queue.
+ ///
+ ///
+ public XBeePacket GetFirstExplicitDataPacket(int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstExplicitDataPacket(0);
+ // Wait for a timeout or until an explicit data XBee packet is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstExplicitDataPacket(0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (IsExplicitDataPacket(xbeePacket))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first explicit data packet from the queue whose 64-bit source address matches the
+ /// address of the provided remote XBee device.
+ ///
+ /// The methods waits up to the specified timeout if necessary for an XBee explicit data
+ /// packet to become available. null if the queue is empty or there is not any XBee explicit
+ /// data packet sent by the provided remote XBee device.
+ /// The XBee device containing the 64-bit address to look for in the
+ /// list of packets.
+ /// The time in milliseconds to wait for an XBee explicit data packet from
+ /// the specified remote XBee device to become available. 0 to return immediately.
+ /// The first XBee explicit data packet whose its 64-bit address matches the address of the
+ /// provided remote XBee device. null if no explicit data packets from the specified XBee
+ /// device are found in the queue.
+ ///
+ ///
+ ///
+ public XBeePacket GetFirstExplicitDataPacketFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstExplicitDataPacketFrom(remoteXBeeDevice, 0);
+ // Wait for a timeout or until an XBee explicit data packet
+ // from remoteXBeeDevice is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstExplicitDataPacketFrom(remoteXBeeDevice, 0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (IsExplicitDataPacket(xbeePacket) && AddressesMatch(xbeePacket, remoteXBeeDevice))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first User Data Relay packet from the queue waiting up to the specified timeout if
+ /// necessary for the packet to become available. null if the queue is empty or there is not
+ /// any User Data Relay packet inside.
+ ///
+ /// The time in milliseconds to wait for a User Data Relay packet to become
+ /// available. 0 to return immediately.
+ ///
+ /// The first User Data Relay packet from the queue, null if it is empty or no data
+ /// packets are contained in the queue.
+ ///
+ ///
+ public XBeePacket GetFirstUserDataRelayPacket(int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstUserDataRelayPacket(0);
+ // Wait for a timeout or until a User Data Relay packet is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstUserDataRelayPacket(0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (IsUserDataRelayPacket(xbeePacket))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first IP data packet from the queue waiting up to the specified timeout if necessary
+ /// for an IP data packet to become available. null if the queue is empty or there is not any
+ /// IP data packet inside.
+ ///
+ /// The time in milliseconds to wait for an IP data packet to become available.
+ /// 0 to return immediately.
+ /// The first IP data packet from the queue, null if it is empty or no IP packets are
+ /// contained in the queue.
+ ///
+ public XBeePacket GetFirstIPDataPacket(int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstIPDataPacket(0);
+ // Wait for a timeout or until a IP data packet is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstIPDataPacket(0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (IsIPDataPacket(xbeePacket))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns the first IP data packet from the queue whose IP address matches the provided address.
+ ///
+ /// The IP address to look for in the list of packets.
+ /// The time in milliseconds to wait for an IP data packet to become
+ /// available. 0 to return immediately.
+ /// The first IP packet whose IP address matches the provided IP address. null if
+ /// no IP data packets from the specified IP address are found in the queue.
+ ///
+ ///
+ public XBeePacket GetFirstIPDataPacketFrom(IPAddress ipAddress, int timeout)
+ {
+ if (timeout > 0)
+ {
+ XBeePacket xbeePacket = GetFirstIPDataPacketFrom(ipAddress, 0);
+ // Wait for a timeout or until a IP data packet with the
+ // provided IP address is read.
+ long deadLine = CurrentTimeMillis() + timeout;
+ while (xbeePacket == null && deadLine > CurrentTimeMillis())
+ {
+ Sleep(100);
+ xbeePacket = GetFirstIPDataPacketFrom(ipAddress, 0);
+ }
+ return xbeePacket;
+ }
+ else
+ {
+ for (int i = 0; i < packetsList.Count; i++)
+ {
+ XBeePacket xbeePacket = packetsList.ElementAt(i);
+ if (IsIPDataPacket(xbeePacket) && IPAddressesMatch(xbeePacket, ipAddress))
+ {
+ packetsList.Remove(xbeePacket);
+ return xbeePacket;
+ }
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Returns whether or not the source address of the provided XBee packet matches the address
+ /// of the given remote XBee device.
+ ///
+ /// The XBee packet to compare its address with the remote XBee
+ /// device.
+ /// The remote XBee device to compare its address with the XBee
+ /// packet.
+ /// true if the source address of the provided packet (if it has) matches the
+ /// address of the remote XBee device.
+ ///
+ ///
+ private bool AddressesMatch(XBeePacket xbeePacket, RemoteXBeeDevice remoteXBeeDevice)
+ {
+ if (!(xbeePacket is XBeeAPIPacket))
+ return false;
+ APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).FrameType;
+ switch (packetType)
+ {
+ case APIFrameType.RECEIVE_PACKET:
+ if (remoteXBeeDevice.XBee64BitAddr != null
+ && ((ReceivePacket)xbeePacket).SourceAddress64.Equals(remoteXBeeDevice.XBee64BitAddr))
+ return true;
+ if (remoteXBeeDevice.XBee16BitAddr != null
+ && ((ReceivePacket)xbeePacket).SourceAddress16.Equals(remoteXBeeDevice.XBee16BitAddr))
+ return true;
+ break;
+ case APIFrameType.REMOTE_AT_COMMAND_RESPONSE:
+ if (remoteXBeeDevice.XBee64BitAddr != null
+ && ((RemoteATCommandResponsePacket)xbeePacket).SourceAddress64.Equals(remoteXBeeDevice.XBee64BitAddr))
+ return true;
+ if (remoteXBeeDevice.XBee16BitAddr != null
+ && ((RemoteATCommandResponsePacket)xbeePacket).SourceAddress16.Equals(remoteXBeeDevice.XBee16BitAddr))
+ return true;
+ break;
+ case APIFrameType.RX_16:
+ if (((RX16Packet)xbeePacket).SourceAddress16.Equals(remoteXBeeDevice.XBee16BitAddr))
+ return true;
+ break;
+ case APIFrameType.RX_64:
+ if (((RX64Packet)xbeePacket).SourceAddress64.Equals(remoteXBeeDevice.XBee64BitAddr))
+ return true;
+ break;
+ case APIFrameType.RX_IO_16:
+ if (((RX16IOPacket)xbeePacket).SourceAddress16.Equals(remoteXBeeDevice.XBee16BitAddr))
+ return true;
+ break;
+ case APIFrameType.RX_IO_64:
+ if (((RX64IOPacket)xbeePacket).SourceAddress64.Equals(remoteXBeeDevice.XBee64BitAddr))
+ return true;
+ break;
+ case APIFrameType.EXPLICIT_RX_INDICATOR:
+ if (((ExplicitRxIndicatorPacket)xbeePacket).SourceAddress64.Equals(remoteXBeeDevice.XBee64BitAddr))
+ return true;
+ break;
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ ///
+ /// Returns whether or not the IP address of the XBee packet matches the provided one.
+ ///
+ /// The XBee packet to compare its IP address with the provided
+ /// one.
+ /// The IP address to be compared with the XBee packet's one.
+ /// true if the IP address of the XBee packet (if it has) matches the
+ /// provided one. false otherwise.
+ private bool IPAddressesMatch(XBeePacket xbeePacket, IPAddress ipAddress)
+ {
+ if (xbeePacket == null || ipAddress == null || !(xbeePacket is XBeeAPIPacket))
+ return false;
+ APIFrameType packetType = (xbeePacket as XBeeAPIPacket).FrameType;
+ switch (packetType)
+ {
+ case APIFrameType.RX_IPV4:
+ if ((xbeePacket as RXIPv4Packet).SourceAddress.Equals(ipAddress))
+ return true;
+ break;
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ ///
+ /// Returns whether or not the given XBee packet is a data packet.
+ ///
+ /// The XBee packet to check if is data packet.
+ /// true if the XBee packet is a data packet, false otherwise.
+ private bool IsDataPacket(XBeePacket xbeePacket)
+ {
+ if (!(xbeePacket is XBeeAPIPacket))
+ return false;
+ APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).FrameType;
+ switch (packetType)
+ {
+ case APIFrameType.RECEIVE_PACKET:
+ case APIFrameType.RX_16:
+ case APIFrameType.RX_64:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ ///
+ /// Returns whether or not the given XBee packet is an explicit data packet.
+ ///
+ /// The XBee packet to check if is an explicit data packet.
+ /// true if the XBee packet is an explicit data packet, false
+ /// otherwise.
+ ///
+ ///
+ private bool IsExplicitDataPacket(XBeePacket xbeePacket)
+ {
+ if (!(xbeePacket is XBeeAPIPacket))
+ return false;
+ APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).FrameType;
+ return packetType == APIFrameType.EXPLICIT_RX_INDICATOR;
+ }
+
+ ///
+ /// Returns whether the given XBee packet is a User Data Relay packet or not.
+ ///
+ /// The XBee packet to check if is a User Data Relay packet.
+ /// true if the XBee packet is an User Data Relay packet, false
+ /// otherwise.
+ ///
+ ///
+ private bool IsUserDataRelayPacket(XBeePacket xbeePacket)
+ {
+ if (!(xbeePacket is XBeeAPIPacket))
+ return false;
+ APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).FrameType;
+ return packetType == APIFrameType.USER_DATA_RELAY_OUTPUT;
+ }
+
+ ///
+ /// Returns whether or not the given XBee packet is an IP data packet.
+ ///
+ /// The XBee packet to check if is an IP data packet.
+ /// true if the XBee packet is an IP data packet, false
+ /// otherwise.
+ private bool IsIPDataPacket(XBeePacket xbeePacket)
+ {
+ if (!(xbeePacket is XBeeAPIPacket))
+ return false;
+ APIFrameType packetType = ((XBeeAPIPacket)xbeePacket).FrameType;
+ return packetType == APIFrameType.RX_IPV4;
+ }
+
+ ///
+ /// Sleeps the thread for the given number of milliseconds.
+ ///
+ /// The number of milliseconds that the thread should be
+ /// sleeping.
+ private void Sleep(int milliseconds)
+ {
+ Task.Delay(milliseconds).Wait();
+ }
+
+ ///
+ /// Gets the current size of the XBee packets queue.
+ ///
+ /// The current size of the XBee packets queue.
+ public int CurrentSize
+ {
+ get
+ {
+ return packetsList.Count;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/XBeeLibrary/Models/XBeeProtocol.cs b/XBeeLibrary.Core/Models/XBeeProtocol.cs
similarity index 61%
rename from XBeeLibrary/Models/XBeeProtocol.cs
rename to XBeeLibrary.Core/Models/XBeeProtocol.cs
index b5db7df..893f871 100644
--- a/XBeeLibrary/Models/XBeeProtocol.cs
+++ b/XBeeLibrary.Core/Models/XBeeProtocol.cs
@@ -1,205 +1,302 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Kveer.XBeeApi.Models
-{
- ///
- /// Enumerates the available XBee protocols. The XBee protocol is determined by the combination of hardware and firmware of an XBee device.
- ///
- public enum XBeeProtocol
- {
- ZIGBEE = 0,
- RAW_802_15_4 = 1,
- XBEE_WIFI = 2,
- DIGI_MESH = 3,
- XCITE = 4,
- XTEND = 5,
- XTEND_DM = 6,
- SMART_ENERGY = 7,
- DIGI_POINT = 8,
- ZNET = 9,
- XC = 10,
- XLR = 11,
- XLR_DM = 12,
- UNKNOWN = 99
- }
-
- public static class XBeeProtocolExtensions
- {
- static IDictionary lookupTable = new Dictionary();
-
- static XBeeProtocolExtensions()
- {
- lookupTable.Add(XBeeProtocol.ZIGBEE, "ZigBee");
- lookupTable.Add(XBeeProtocol.RAW_802_15_4, "802.15.4");
- lookupTable.Add(XBeeProtocol.XBEE_WIFI, "Wi-Fi");
- lookupTable.Add(XBeeProtocol.DIGI_MESH, "DigiMesh");
- lookupTable.Add(XBeeProtocol.XCITE, "XCite");
- lookupTable.Add(XBeeProtocol.XTEND, "XTend (Legacy)");
- lookupTable.Add(XBeeProtocol.XTEND_DM, "XTend (DigiMesh)");
- lookupTable.Add(XBeeProtocol.SMART_ENERGY, "Smart Energy");
- lookupTable.Add(XBeeProtocol.DIGI_POINT, "Point-to-multipoint");
- lookupTable.Add(XBeeProtocol.ZNET, "ZNet 2.5");
- lookupTable.Add(XBeeProtocol.XC, "XSC");
- lookupTable.Add(XBeeProtocol.XLR, "XLR");
- lookupTable.Add(XBeeProtocol.XLR_DM, "XLR"); // TODO [XLR_DM] XLR device with DigiMesh support.
- lookupTable.Add(XBeeProtocol.UNKNOWN, "Unknown");
- }
-
- ///
- /// Gets the XBee protocol ID.
- ///
- ///
- /// XBee protocol ID.
- public static int GetID(this XBeeProtocol source)
- {
- return (int)source;
- }
-
- ///
- /// Gets the XBee protocol description.
- ///
- ///
- /// XBee protocol description.
- public static string GetDescription(this XBeeProtocol source)
- {
- return lookupTable[source];
- }
-
- ///
- /// Gets the