/// <summary> /// Discovers and reports the first remote XBee device that matches the supplied identifier. /// </summary> /// <remarks>This method blocks until the configured timeout in the device (NT) expires.</remarks> /// <param name="id">The identifier of the device to be discovered.</param> /// <returns>The discovered remote XBee device with the given identifier, <c>null</c> if the /// timeout expires and the device was not found.</returns> /// <exception cref="InterfaceNotOpenException">If this device connection is not open.</exception> /// <exception cref="XBeeException">If there is an error discovering the device.</exception> /// <seealso cref="DiscoverDevices(IList{string})"/> public RemoteXBeeDevice DiscoverDevice(string id) { // Check if the connection is open. if (!localDevice.IsOpen) { throw new InterfaceNotOpenException(); } logger.DebugFormat("{0}ND for {1} device.", xbeeDevice.ToString(), id); IsRunning = true; discovering = true; PerformNodeDiscovery(id); XBeeNetwork network = localDevice.GetNetwork(); RemoteXBeeDevice rDevice = null; if (deviceList != null && deviceList.Count > 0) { rDevice = deviceList[0]; if (rDevice != null) { rDevice = network.AddRemoteDevice(rDevice); } } return(rDevice); }
/// <summary> /// Returns the 16-bit address of the given remote device. /// </summary> /// <param name="device">The remote device to get its 16-bit address.</param> /// <returns>The 16-bit address of the device, <c>null</c> if it does not contain a valid one.</returns> /// <seealso cref="RemoteXBeeDevice"/> /// <seealso cref="XBee16BitAddress"/> private XBee16BitAddress Get16BitAddress(RemoteXBeeDevice device) { if (device == null) { return(null); } XBee16BitAddress address = null; switch (device.XBeeProtocol) { case XBeeProtocol.RAW_802_15_4: address = ((RemoteRaw802Device)device).XBee16BitAddr; break; case XBeeProtocol.ZIGBEE: address = ((RemoteZigBeeDevice)device).XBee16BitAddr; break; default: // TODO should we allow this operation for general remote devices? address = device.XBee16BitAddr; break; } return(address); }
/// <summary> /// Adds the given list of remote devices to the network. /// </summary> /// <remarks>Notice that this operation does not join the remote XBee devices to the network; it /// just tells the network that it contains those devices. However, the devices have only been /// added to the device list, and may not be physically in the same network. /// /// The way of adding a device to the network is based on the 64-bit address. If it is not /// configured: /// <list type="bullet"> /// <item><description>For 802.15.4 and ZigBee devices, the 16-bit address will be used instead.</description></item> /// <item><description>For the rest will return <c>true</c> as the result of the addition.</description></item> /// </list></remarks> /// <param name="list">The list of remote devices to be added to the network.</param> /// <returns>A list with the successfully added devices to the network.</returns> /// <exception cref="ArgumentNullException">If <c><paramref name="list"/> == null</c>.</exception> public List <RemoteXBeeDevice> AddRemoteDevices(IList <RemoteXBeeDevice> list) { if (list == null) { throw new ArgumentNullException("The list of remote devices cannot be null."); } List <RemoteXBeeDevice> addedList = new List <RemoteXBeeDevice>(list.Count); if (list.Count == 0) { return(addedList); } logger.DebugFormat("{0}Adding '{1}' devices to network.", localDevice.ToString(), list.Count); for (int i = 0; i < list.Count; i++) { RemoteXBeeDevice d = AddRemoteDevice(list[i]); if (d != null) { addedList.Add(d); } } return(addedList); }
/// <summary> /// Removes the given remote XBee device from the network. /// </summary> /// <remarks>Notice that this operation does not remove the remote XBee device from the actual XBee /// network; it just tells the network object that it will no longer contain that device. However, /// next time a discovery is performed, it could be added again automatically. /// /// This method will check for a device that matches the 64-bit address of the provided one, if /// found, that device will be removed from the corresponding list. In case the 64-bit address is /// not defined, it will use the 16-bit address for DigiMesh and ZigBee devices.</remarks> /// <param name="remoteDevice">The remote device to be removed from the network.</param> /// <exception cref="ArgumentNullException">If <c><paramref name="remoteDevice"/> == null</c>.</exception> public void RemoveRemoteDevice(RemoteXBeeDevice remoteDevice) { if (remoteDevice == null) { throw new ArgumentNullException("Remote device cannot be null."); } RemoteXBeeDevice devInNetwork = null; // Look in the 64-bit map. XBee64BitAddress addr64 = remoteDevice.XBee64BitAddr; if (addr64 != null && !addr64.Equals(XBee64BitAddress.UNKNOWN_ADDRESS)) { if (remotesBy64BitAddr.TryRemove(addr64, out devInNetwork)) { return; } } // If not found, look in the 16-bit map. XBee16BitAddress addr16 = Get16BitAddress(remoteDevice); if (addr16 != null && !addr16.Equals(XBee16BitAddress.UNKNOWN_ADDRESS)) { // The preference order is: // 1.- Look in the 64-bit map // 2.- Then in the 16-bit map. // This should be maintained in the 'getDeviceBy16BitAddress' method. // Look for the 16-bit address in the 64-bit map. ICollection <RemoteXBeeDevice> devices = remotesBy64BitAddr.Values; foreach (RemoteXBeeDevice d in devices) { XBee16BitAddress a = Get16BitAddress(d); if (a != null && a.Equals(addr16)) { remotesBy64BitAddr.TryRemove(d.XBee64BitAddr, out RemoteXBeeDevice r); return; } } // If not found, look for the 16-bit address in the 16-bit map. // Remove the device. if (remotesBy16BitAddr.TryRemove(addr16, out devInNetwork)) { return; } } // If the device does not contain a valid address log an error. if ((addr64 == null || addr64.Equals(XBee64BitAddress.UNKNOWN_ADDRESS)) && (addr16 == null || addr16.Equals(XBee16BitAddress.UNKNOWN_ADDRESS))) { logger.ErrorFormat("{0}Remote device '{1}' cannot be removed: 64-bit and 16-bit addresses must be specified.", localDevice.ToString(), remoteDevice.ToString()); } }
/// <summary> /// Notifies the given discovery listeners that a device was discovered. /// </summary> /// <param name="remoteDevice">The remote device discovered.</param> private void NotifyDeviceDiscovered(RemoteXBeeDevice remoteDevice) { logger.DebugFormat("{0}Device discovered: {1}.", xbeeDevice, remoteDevice); if (DeviceDiscovered == null) { lock (deviceList) { if (deviceList != null) { if (!deviceList.Any(d => d.XBee64BitAddr == remoteDevice.XBee64BitAddr)) { deviceList.Add(remoteDevice); } } } return; } XBeeNetwork network = localDevice.GetNetwork(); RemoteXBeeDevice addedDev = network.AddRemoteDevice(remoteDevice); if (addedDev != null) { try { lock (DeviceDiscovered) { var handler = DeviceDiscovered; if (handler != null) { var args = new DeviceDiscoveredEventArgs(addedDev); handler.GetInvocationList().AsParallel().ForAll((action) => { action.DynamicInvoke(this, args); }); } } } catch (Exception e) { logger.Error(e.Message, e); } } else { string error = "Error adding device '" + remoteDevice + "' to the network."; NotifyDiscoveryError(error); } }
/// <summary> /// Returns the remote device already contained in the network whose 16-bit address matches the /// given one. /// </summary> /// <remarks>Note that this method does not perform a discovery, only returns the device that has /// been previously discovered.</remarks> /// <param name="address">The 16-bit address of the device to be retrieved.</param> /// <returns>The remote device in the network or <c>null</c> if it is not found.</returns> /// <exception cref="ArgumentException">If <paramref name="address"/> is /// <see cref="XBee16BitAddress.UNKNOWN_ADDRESS"/>.</exception> /// <exception cref="ArgumentNullException">If <c><paramref name="address"/> == null</c>.</exception> /// <exception cref="OperationNotSupportedException">If the protocol of <c>localDevice</c> is /// <see cref="XBeeProtocol.DIGI_MESH"/> or if it is <see cref="XBeeProtocol.DIGI_POINT"/></exception> public RemoteXBeeDevice GetDevice(XBee16BitAddress address) { if (localDevice.XBeeProtocol == XBeeProtocol.DIGI_MESH) { throw new OperationNotSupportedException("DigiMesh protocol does not support 16-bit addressing."); } if (localDevice.XBeeProtocol == XBeeProtocol.DIGI_POINT) { throw new OperationNotSupportedException("Point-to-Multipoint protocol does not support 16-bit addressing."); } if (address == null) { throw new ArgumentNullException("16-bit address cannot be null."); } if (address.Equals(XBee16BitAddress.UNKNOWN_ADDRESS)) { throw new ArgumentException("16-bit address cannot be unknown."); } logger.DebugFormat("{0}Getting device '{1}' from network.", localDevice.ToString(), address); // The preference order is: // 1.- Look in the 64-bit map // 2.- Then in the 16-bit map. // This should be maintained in the 'addRemoteDevice' method. RemoteXBeeDevice devInNetwork = null; // Look in the 64-bit map. ICollection <RemoteXBeeDevice> devices = remotesBy64BitAddr.Values; foreach (RemoteXBeeDevice d in devices) { XBee16BitAddress a = Get16BitAddress(d); if (a != null && a.Equals(address)) { devInNetwork = d; break; } } // Look in the 16-bit map. if (devInNetwork == null) { remotesBy16BitAddr.TryGetValue(address, out devInNetwork); } return(devInNetwork); }
/// <summary> /// Discovers and reports all remote XBee devices that match the supplied identifiers. /// </summary> /// <remarks>This method blocks until the configured timeout in the device (NT) expires.</remarks> /// <param name="ids">List which contains the identifiers of the devices to be discovered.</param> /// <returns>A list of the discovered remote XBee devices with the given identifiers.</returns> /// <exception cref="InterfaceNotOpenException">If this device connection is not open.</exception> /// <exception cref="XBeeException">If there is an error discovering the device.</exception> /// <seealso cref="DiscoverDevice(string)"/> public List <RemoteXBeeDevice> DiscoverDevices(IList <string> ids) { // Check if the connection is open. if (!localDevice.IsOpen) { throw new InterfaceNotOpenException(); } logger.DebugFormat("{0} ND for all '[{1}]' devices.", xbeeDevice.ToString(), string.Join(", ", ids)); IsRunning = true; discovering = true; PerformNodeDiscovery(null); List <RemoteXBeeDevice> foundDevices = new List <RemoteXBeeDevice>(0); if (deviceList == null) { return(foundDevices); } XBeeNetwork network = localDevice.GetNetwork(); foreach (RemoteXBeeDevice d in deviceList) { string nID = d.NodeID; if (nID == null) { continue; } foreach (string id in ids) { if (nID.Equals(id)) { RemoteXBeeDevice rDevice = network.AddRemoteDevice(d); if (rDevice != null && !foundDevices.Contains(rDevice)) { foundDevices.Add(rDevice); } } } } return(foundDevices); }
/// <summary> /// Callback called after a discovery packet is received and the corresponding Packet Received event /// has been fired. /// </summary> /// <param name="sender">The object that sent the event.</param> /// <param name="e">The Packet Received event.</param> /// <param name="id">The ID of the device to find.</param> public async void DiscoveryPacketReceived(object sender, PacketReceivedEventArgs e, string id) { if (!discovering) { return; } RemoteXBeeDevice rdevice = null; byte[] commandValue = GetRemoteDeviceData((XBeeAPIPacket)e.ReceivedPacket); rdevice = await ParseDiscoveryAPIData(commandValue, localDevice); // If a device with a specific id is being searched and it was // already found, return it. if (id != null) { if (rdevice != null && id.Equals(rdevice.NodeID)) { lock (deviceList) { if (deviceList != null) { if (!deviceList.Any(d => d.XBee64BitAddr == rdevice.XBee64BitAddr)) { deviceList.Add(rdevice); } } } // If the local device is 802.15.4 wait until the 'end' command is received. if (xbeeDevice.XBeeProtocol != XBeeProtocol.RAW_802_15_4) { discovering = false; } } } else if (rdevice != null) { NotifyDeviceDiscovered(rdevice); } }
/// <summary> /// 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. /// </summary> /// <remarks>This method blocks till a success or error response arrives or the configured receive timeout /// expires.</remarks> /// <param name="remoteXBeeDevice">The XBee device of the network that will receive the data.</param> /// <param name="sourceEndpoint">Source endpoint for the transmission.</param> /// <param name="destEndpoint">Destination endpoint for the transmission.</param> /// <param name="clusterID">Cluster ID used in the transmission.</param> /// <param name="profileID">Profile ID used in the transmission.</param> /// <param name="data">Byte array containing the data to be sent.</param> /// <exception cref="ArgumentNullException">If <c><paramref name="remoteXBeeDevice"/> == null</c> /// or if <c><paramref name="data"/> == null</c>.</exception> /// <exception cref="ArgumentException">If <c>clusterID.Length != 2</c> /// or if <c>profileID.Length != 2</c>.</exception> /// <exception cref="InterfaceNotOpenException">If the interface is not open.</exception> /// <exception cref="TimeoutException">If there is a timeout sending the given packet synchronously.</exception> /// <exception cref="TransmitException">If the transmit status generated when sending the packet is not /// an instance of <see cref="TransmitStatusPacket"/> /// or if it is not an instance of <see cref="Packet.Raw.TXStatusPacket"/> /// or if when it is correct, its status is different from <see cref="XBeeTransmitStatus.SUCCESS"/>.</exception> /// <exception cref="XBeeException">If there is any other XBee related error.</exception> /// <seealso cref="RemoteXBeeDevice"/> /// <seealso cref="AbstractXBeeDevice.SendExplicitData(RemoteXBeeDevice, byte, byte, byte[], byte[], byte[])"/> public new void SendExplicitData(RemoteXBeeDevice remoteXBeeDevice, byte sourceEndpoint, byte destEndpoint, byte[] clusterID, byte[] profileID, byte[] data) { base.SendExplicitData(remoteXBeeDevice, sourceEndpoint, destEndpoint, clusterID, profileID, data); }
/// <summary> /// Reads new explicit data received from the given remote XBee device during the provided timeout. /// </summary> /// <remarks> /// 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 <see cref="AbstractXBeeDevice.ExplicitDataReceived"/>. /// </remarks> /// <param name="remoteXBeeDevice">The remote device to read explicit data from.</param> /// <param name="timeout">The time to wait for new explicit data in milliseconds.</param> /// <returns>An <see cref="ExplicitXBeeMessage"/> object containing the explicit data, the source /// address of the remote node that sent the data and other values related to the transmission. /// <c>null</c> if this device did not receive new data from the provided remote XBee device /// during <paramref name="timeout"/> milliseconds.</returns> /// <exception cref="ArgumentException">If <c><paramref name="timeout"/> <![CDATA[<]]> 0</c>.</exception> /// <exception cref="ArgumentNullException">If <c><paramref name="remoteXBeeDevice"/> == null</c>.</exception> /// <exception cref="InterfaceNotOpenException">If the interface is not open.</exception> /// <seealso cref="ExplicitXBeeMessage"/> /// <seealso cref="RemoteXBeeDevice"/> /// <seealso cref="AbstractXBeeDevice.ReadExplicitDataFrom(RemoteXBeeDevice, int)"/> public new ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice, int timeout) { return(base.ReadExplicitDataFrom(remoteXBeeDevice, timeout)); }
/// <summary> /// Reads new explicit data received from the given remote XBee device during the configured /// receive timeout. /// </summary> /// <remarks> /// 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 <see cref="AbstractXBeeDevice.ExplicitDataReceived"/>. /// </remarks> /// <param name="remoteXBeeDevice">The remote device to read explicit data from.</param> /// <returns>An <see cref="ExplicitXBeeMessage"/> object containing the explicit data, the source /// address of the remote node that sent the data and other values related to the transmission. /// <c>null</c> if this device did not receive new explicit data from the provided remote XBee /// device during the configured receive timeout.</returns> /// <exception cref="ArgumentNullException">If <c><paramref name="remoteXBeeDevice"/> == null</c>.</exception> /// <exception cref="InterfaceNotOpenException">If the interface is not open.</exception> /// <seealso cref="ExplicitXBeeMessage"/> /// <seealso cref="RemoteXBeeDevice"/> /// <seealso cref="AbstractXBeeDevice.ReadExplicitDataFrom(RemoteXBeeDevice)"/> public new ExplicitXBeeMessage ReadExplicitDataFrom(RemoteXBeeDevice remoteXBeeDevice) { return(base.ReadExplicitDataFrom(remoteXBeeDevice)); }
/// <summary> /// Reads new data received from the given remote XBee device during the configured received /// timeout. /// </summary> /// <remarks>This method blocks until new data is received or the provided timeout expires. /// /// The receive timeout can be consulted/configured using the <see cref="ReceiveTimeout"/> /// property.</remarks> /// <param name="remoteXBeeDevice">The remote device to read data from.</param> /// <returns>An <see cref="XBeeMessage"/> object containing the data and the source address of /// the remote node that sent the data. <c>null</c> if this did not receive new data during /// the configured timeout.</returns> /// <exception cref="ArgumentNullException">If <paramref name="remoteXBeeDevice"/> is <c>null</c>.</exception> /// <exception cref="InterfaceNotOpenException">If this device connection is not open.</exception> /// <seealso cref="ReceiveTimeout"/> /// <seealso cref="ReadData()"/> /// <seealso cref="ReadData(int)"/> /// <seealso cref="ReadDataFrom(RemoteXBeeDevice, int)"/> /// <seealso cref="RemoteXBeeDevice"/> /// <seealso cref="XBeeMessage"/> public new XBeeMessage ReadDataFrom(RemoteXBeeDevice remoteXBeeDevice) { return(base.ReadDataFrom(remoteXBeeDevice)); }
/// <summary> /// Sends the provided data to the given XBee device choosing the optimal send method depending /// on the protocol of the local XBee device. /// </summary> /// <remarks>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 <see cref="ReceiveTimeout"/> property. /// /// For non-blocking operations use the method <see cref="SendData(RemoteXBeeDevice, byte[])"/>.</remarks> /// <param name="xbeeDevice">The XBee device of the network that will receive the data.</param> /// <param name="data">Byte array containing the data to be sent.</param> /// <exception cref="ArgumentNullException">If <c><paramref name="xbeeDevice"/> == null</c> /// or if <c><paramref name="data"/> == null</c>.</exception> /// <exception cref="InterfaceNotOpenException">If this device connection is not open.</exception> /// <exception cref="OperationNotSupportedException">If the sender device is remote.</exception> /// <exception cref="TimeoutException">If there is a timeout sending the data.</exception> /// <exception cref="TransmitException">If the transmit status generated when sending the packet is not /// an instance of <see cref="Packet.Common.TransmitStatusPacket"/> /// or if it is not an instance of <see cref="Packet.Raw.TXStatusPacket"/> /// or if when it is correct, its status is different from <see cref="XBeeTransmitStatus.SUCCESS"/>.</exception> /// <exception cref="XBeeException">If there is any other XBee related error.</exception> /// <seealso cref="ReceiveTimeout"/> /// <seealso cref="RemoteXBeeDevice"/> /// <seealso cref="SendDataAsync(RemoteXBeeDevice, byte[])"/> public virtual new void SendData(RemoteXBeeDevice xbeeDevice, byte[] data) { base.SendData(xbeeDevice, data); }
/// <summary> /// Parses the given node discovery API data to create and return a remote /// XBee Device. /// </summary> /// <param name="data">Byte array with the data to parse.</param> /// <param name="localDevice">The local device that received the remote XBee data.</param> /// <returns>The discovered XBee device.</returns> private async Task <RemoteXBeeDevice> ParseDiscoveryAPIData(byte[] data, AbstractXBeeDevice localDevice) { if (data == null) { return(null); } RemoteXBeeDevice device = null; XBee16BitAddress addr16 = null; XBee64BitAddress addr64 = null; string id = null; // TODO role of the device: coordinator, router, end device or unknown. //XBeeDeviceType role = XBeeDeviceType.UNKNOWN; int signalStrength = 0; byte[] profileID = null; byte[] manufacturerID = null; using (var inputStream = new MemoryStream(data)) { // Read 16 bit address. addr16 = new XBee16BitAddress(await ByteUtils.ReadBytes(2, inputStream)); // Read 64 bit address. addr64 = new XBee64BitAddress(await ByteUtils.ReadBytes(8, inputStream)); switch (localDevice.XBeeProtocol) { case XBeeProtocol.ZIGBEE: case XBeeProtocol.DIGI_MESH: case XBeeProtocol.ZNET: 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: case XBeeProtocol.SX: // Read node identifier. id = ByteUtils.ReadString(inputStream); // Read parent address. XBee16BitAddress parentAddress = new XBee16BitAddress(await ByteUtils.ReadBytes(2, inputStream)); // TODO Read device type. //role = XBeeDeviceType.get(inputStream.read()); // Consume status byte, it is not used yet. await ByteUtils.ReadBytes(1, inputStream); // Read profile ID. profileID = await ByteUtils.ReadBytes(2, inputStream); // Read manufacturer ID. manufacturerID = await ByteUtils.ReadBytes(2, inputStream); logger.DebugFormat("{0}Discovered {1} device: 16-bit[{2}], 64-bit[{3}], id[{4}], parent[{5}], profile[{6}], manufacturer[{7}].", xbeeDevice.ToString(), localDevice.XBeeProtocol.GetDescription(), addr16, addr64, id, parentAddress, HexUtils.ByteArrayToHexString(profileID), HexUtils.ByteArrayToHexString(manufacturerID)); break; case XBeeProtocol.RAW_802_15_4: // Read strength signal byte. signalStrength = inputStream.ReadByte(); // Read node identifier. id = ByteUtils.ReadString(inputStream); logger.DebugFormat("{0}Discovered {1} device: 16-bit[{2}], 64-bit[{3}], id[{4}], rssi[{5}].", xbeeDevice.ToString(), localDevice.XBeeProtocol.GetDescription(), addr16, addr64, id, signalStrength); break; case XBeeProtocol.UNKNOWN: default: logger.DebugFormat("{0}Discovered {1} device: 16-bit[{2}], 64-bit[{3}].", xbeeDevice.ToString(), localDevice.XBeeProtocol.GetDescription(), addr16, addr64); break; } // Create device and fill with parameters. switch (localDevice.XBeeProtocol) { case XBeeProtocol.ZIGBEE: device = new RemoteZigBeeDevice(localDevice, addr64, addr16, id /*, role*/); // TODO profileID and manufacturerID break; case XBeeProtocol.DIGI_MESH: device = new RemoteDigiMeshDevice(localDevice, addr64, id /*, role*/); // TODO profileID and manufacturerID break; case XBeeProtocol.DIGI_POINT: device = new RemoteDigiPointDevice(localDevice, addr64, id /*, role*/); // TODO profileID and manufacturerID break; case XBeeProtocol.RAW_802_15_4: device = new RemoteRaw802Device(localDevice, addr64, addr16, id /*, role*/); // TODO signalStrength break; default: device = new RemoteXBeeDevice(localDevice, addr64, addr16, id /*, role*/); break; } } return(device); }
/// <summary> /// Adds the given remote device to the network. /// </summary> /// <remarks>Notice that this operation does not join the remote XBee device to the network; it /// just tells the network that it contains that device. However, the device has only been added /// to the device list, and may not be physically in the same network. /// /// The way of adding a device to the network is based on the 64-bit address. If it is not /// configured: /// <list type="bullet"> /// <item><description>For 802.15.4 and ZigBee devices, it will use the 16-bit address.</description></item> /// <item><description>For the rest will return <c>true</c> as the result of the addition.</description></item> /// </list></remarks> /// <param name="remoteDevice">The remote device to be added to the network.</param> /// <returns>The remote XBee Device instance in the network, <c>null</c> if the device could not be /// successfully added.</returns> /// <exception cref="ArgumentNullException">If <c><paramref name="remoteDevice"/> == null</c>.</exception> public RemoteXBeeDevice AddRemoteDevice(RemoteXBeeDevice remoteDevice) { if (remoteDevice == null) { throw new ArgumentNullException("Remote device cannot be null."); } logger.DebugFormat("{0}Adding device '{1}' to network.", localDevice.ToString(), remoteDevice.ToString()); RemoteXBeeDevice devInNetwork = null; XBee64BitAddress addr64 = remoteDevice.XBee64BitAddr; XBee16BitAddress addr16 = Get16BitAddress(remoteDevice); // Check if the device has 64-bit address. if (addr64 != null && !addr64.Equals(XBee64BitAddress.UNKNOWN_ADDRESS)) { // The device has 64-bit address, so look in the 64-bit map. if (remotesBy64BitAddr.TryGetValue(addr64, out devInNetwork)) { // The device exists in the 64-bit map, so update the reference and return it. logger.DebugFormat("{0}Existing device '{1}' in network.", localDevice.ToString(), devInNetwork.ToString()); devInNetwork.UpdateDeviceDataFrom(remoteDevice); return(devInNetwork); } else { // The device does not exist in the 64-bit map, so check its 16-bit address. if (addr16 != null && !addr16.Equals(XBee16BitAddress.UNKNOWN_ADDRESS)) { // The device has 16-bit address, so look in the 16-bit map. if (remotesBy16BitAddr.TryGetValue(addr16, out devInNetwork)) { // The device exists in the 16-bit map, so remove it and add it to the 64-bit map. logger.DebugFormat("{0}Existing device '{1}' in network.", localDevice.ToString(), devInNetwork.ToString()); remotesBy16BitAddr.TryRemove(addr16, out devInNetwork); devInNetwork.UpdateDeviceDataFrom(remoteDevice); remotesBy64BitAddr.AddOrUpdate(addr64, devInNetwork, (k, v) => devInNetwork); return(devInNetwork); } else { // The device does not exist in the 16-bit map, so add it to the 64-bit map. remotesBy64BitAddr.AddOrUpdate(addr64, remoteDevice, (k, v) => remoteDevice); return(remoteDevice); } } else { // The device has not 16-bit address, so add it to the 64-bit map. remotesBy64BitAddr.AddOrUpdate(addr64, remoteDevice, (k, v) => remoteDevice); return(remoteDevice); } } } // If the device has not 64-bit address, check if it has 16-bit address. if (addr16 != null && !addr16.Equals(XBee16BitAddress.UNKNOWN_ADDRESS)) { // The device has 16-bit address, so look in the 64-bit map. ICollection <RemoteXBeeDevice> devices = remotesBy64BitAddr.Values; foreach (RemoteXBeeDevice d in devices) { XBee16BitAddress a = Get16BitAddress(d); if (a != null && a.Equals(addr16)) { devInNetwork = d; break; } } // Check if the device exists in the 64-bit map. if (devInNetwork != null) { // The device exists in the 64-bit map, so update the reference and return it. logger.DebugFormat("{0}Existing device '{1}' in network.", localDevice.ToString(), devInNetwork.ToString()); devInNetwork.UpdateDeviceDataFrom(remoteDevice); return(devInNetwork); } else { // The device does not exist in the 64-bit map, so look in the 16-bit map. if (remotesBy16BitAddr.TryGetValue(addr16, out devInNetwork)) { // The device exists in the 16-bit map, so update the reference and return it. logger.DebugFormat("{0}Existing device '{1}' in network.", localDevice.ToString(), devInNetwork.ToString()); devInNetwork.UpdateDeviceDataFrom(remoteDevice); return(devInNetwork); } else { // The device does not exist in the 16-bit map, so add it. remotesBy16BitAddr.AddOrUpdate(addr16, remoteDevice, (k, v) => remoteDevice); return(remoteDevice); } } } // If the device does not contain a valid address, return null. logger.ErrorFormat("{0}Remote device '{1}' cannot be added: 64-bit and 16-bit addresses must be specified.", localDevice.ToString(), remoteDevice.ToString()); return(null); }