/**
         * Removes the given remote XBee device from the network.
         *
         * <p>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.</p>
         *
         * <p>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.</p>
         *
         * @param remoteDevice The remote device to be removed from the network.
         *
         * @throws ArgumentNullException if {@code RemoteDevice == null}.
         *
         * @see #addRemoteDevice(RemoteXBeeDevice)
         * @see #clearDeviceList()
         * @see RemoteXBeeDevice
         */
        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.Get64BitAddress();

            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))
                    {
                        RemoteXBeeDevice r;
                        remotesBy64BitAddr.TryRemove(d.Get64BitAddress(), out 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());
            }
        }
        /**
         * Returns the remote device already contained in the network whose 16-bit
         * address matches the given one.
         *
         * <p>Note that this method <b>does not perform a discovery</b>, only
         * returns the device that has been previously discovered.</p>
         *
         * @param address The 16-bit address of the device to be retrieved.
         *
         * @return The remote device in the network or {@code null} if it is not
         *         found.
         *
         * @throws ArgumentException if {@code address.equals(XBee16BitAddress.UNKNOWN_ADDRESS)}.
         * @throws ArgumentNullException if {@code address == null}.
         * @throws OperationNotSupportedException if the protocol of the local XBee device is DigiMesh or Point-to-Multipoint.
         */
        public RemoteXBeeDevice GetDevice(XBee16BitAddress address)        /*throws OperationNotSupportedException */
        {
            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 ArgumentNullException("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)
            {
                devInNetwork = remotesBy16BitAddr[address];
            }

            return(devInNetwork);
        }
        /**
         * Adds the given remote device to the network.
         *
         * <p>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.</p>
         *
         * <p>The way of adding a device to the network is based on the 64-bit
         * address. If it is not configured:</p>
         *
         * <ul>
         * <li>For 802.15.4 and ZigBee devices, it will use the 16-bit address.</li>
         * <li>For the rest will return {@code false} as the result of the addition.</li>
         * </ul>
         *
         * @param remoteDevice The remote device to be added to the network.
         *
         * @return The remote XBee Device instance in the network, {@code null} if
         *         the device could not be successfully added.
         *
         * @throws ArgumentNullException if {@code RemoteDevice == null}.
         *
         * @see #addRemoteDevices(List)
         * @see #removeRemoteDevice(RemoteXBeeDevice)
         * @see RemoteXBeeDevice
         */
        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.Get64BitAddress();
            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.
                    devInNetwork = remotesBy16BitAddr[addr16];
                    if (devInNetwork != null)
                    {
                        // 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);
        }
Esempio n. 4
0
        /// <summary>
        /// Returns the remote XBee device from where the given package was sent from.
        /// </summary>
        /// <remarks>This is for internal use only.
        ///
        /// If the package does not contain information about the source, this method returns <c>null</c>
        /// (for example, <see cref="ModemStatusPacket"/>).
        ///
        /// 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.</remarks>
        /// <param name="apiPacket">The packet sent from the remote device.</param>
        /// <returns>The remote XBee device that sends the given packet. It may be <c>null</c> if the
        /// packet is not a known frame (<see cref="APIFrameType"/>) or if it does not contain information
        /// of the source device.</returns>
        /// <exception cref="ArgumentNullException">If <c><paramref name="apiPacket"/> == null</c>.</exception>
        /// <exception cref="XBeeException">If any error occurred while adding the device to the
        /// network.</exception>
        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);
        }
        /*throws OperationNotSupportedException */
        /**
         * Returns the remote device already contained in the network whose 16-bit
         * address matches the given one.
         *
         * <p>Note that this method <b>does not perform a discovery</b>, only
         * returns the device that has been previously discovered.</p>
         *
         * @param address The 16-bit address of the device to be retrieved.
         *
         * @return The remote device in the network or {@code null} if it is not
         *         found.
         *
         * @throws ArgumentException if {@code address.equals(XBee16BitAddress.UNKNOWN_ADDRESS)}.
         * @throws ArgumentNullException if {@code address == null}.
         * @throws OperationNotSupportedException if the protocol of the local XBee device is DigiMesh or Point-to-Multipoint.
         */
        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 ArgumentNullException("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)
                devInNetwork = remotesBy16BitAddr[address];

            return devInNetwork;
        }