Пример #1
0
        public void CommandReceived(ZigBeeCommand command)
        {
            // We are only interested in READ ATTRIBUTE commands
            if (!(command is ReadAttributesCommand))
            {
                return;
            }

            ReadAttributesCommand readCommand = (ReadAttributesCommand)command;

            if (readCommand.ClusterId != ZclBasicCluster.CLUSTER_ID && readCommand.CommandDirection != ZclCommandDirection.SERVER_TO_CLIENT)
            {
                return;
            }

            List <ReadAttributeStatusRecord> attributeRecords = new List <ReadAttributeStatusRecord>();

            foreach (ushort attributeId in readCommand.Identifiers)
            {
                attributeRecords.Add(GetAttributeRecord(attributeId));
            }

            ReadAttributesResponse readResponse = new ReadAttributesResponse();

            readResponse.Records            = attributeRecords;
            readResponse.DestinationAddress = readCommand.SourceAddress;
            readResponse.CommandDirection   = ZclCommandDirection.CLIENT_TO_SERVER;
            readResponse.TransactionId      = command.TransactionId;
            _networkManager.SendCommand(readResponse);
        }
Пример #2
0
        public void CommandReceived(ZigBeeCommand command)
        {
            // If we have local servers matching the request, then we need to respond
            if (command is MatchDescriptorRequest matchRequest)
            {
                Log.Debug("{ExtPanId}: ClusterMatcher received request {Match}", _networkManager.ZigBeeExtendedPanId, matchRequest);
                if (matchRequest.ProfileId != 0x104)
                {
                    // TODO: Do we need to restrict the profile? Remove this check?
                    return;
                }

                // We want to match any of our local servers (ie our input clusters) with any
                // requested clusters in the requests cluster list
                if (matchRequest.InClusterList.Intersect(_clusters).Count() == 0 &&
                    matchRequest.OutClusterList.Intersect(_clusters).Count() == 0)
                {
                    Log.Debug("{ExtPanId}: ClusterMatcher no match", _networkManager.ZigBeeExtendedPanId);
                    return;
                }

                MatchDescriptorResponse matchResponse = new MatchDescriptorResponse();
                matchResponse.Status = ZdoStatus.SUCCESS;
                List <ushort> matchList = new List <ushort>();
                matchList.Add(1);
                matchResponse.MatchList = matchList;

                matchResponse.DestinationAddress = command.SourceAddress;
                matchResponse.NwkAddrOfInterest  = matchRequest.NwkAddrOfInterest;
                Log.Debug("{ExtPanId}: ClusterMatcher sending match {Response}", _networkManager.ZigBeeExtendedPanId, matchResponse);
                _networkManager.SendCommand(matchResponse);
            }
        }
Пример #3
0
        /// <summary>
        /// Sends ZigBeeCommand command and uses the ZigBeeTransactionMatcher to match the response.
        /// The task will be timed out if there is no response.
        ///
        /// @param command the ZigBeeCommand
        /// @param responseMatcher the ZigBeeTransactionMatcher
        /// </summary>
        public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher)
        {
            _command         = command;
            _responseMatcher = responseMatcher;

            _timeout = DateTime.Now.AddMilliseconds(DEFAULT_TIMEOUT_MILLISECONDS);

            lock (_command)
            {
                _networkManager.AddCommandListener(this);

                int transactionId = _networkManager.SendCommand(command);

                if (command is ZclCommand cmd)
                {
                    cmd.TransactionId = (byte)transactionId;
                }
            }

            return(await Task.Run(() =>
            {
                while (true)
                {
                    if (DateTime.Now < _timeout)
                    {
                        if (_result != null)
                        {
                            return _result;
                        }
                    }
                    else
                    {
                        _logger.Debug("Transaction timeout: {Command}", _command);
                        lock (_command)
                        {
                            _networkManager.RemoveCommandListener(this);
                            return new CommandResult();
                        }
                    }
                }
            }));
        }
Пример #4
0
        public void CommandReceived(ZigBeeCommand command)
        {
            // If we have local servers matching the request, then we need to respond
            if (command is MatchDescriptorRequest matchRequest)
            {
                Log.Debug("{ExtPanId}: ClusterMatcher received request {Match}", _networkManager.ZigBeeExtendedPanId, matchRequest);
                if (matchRequest.ProfileId != _profileId)
                {
                    Log.Debug("{ExtPanId}: ClusterMatcher no match to profileId", _networkManager.ZigBeeExtendedPanId);
                    return;
                }

                if (matchRequest.NwkAddrOfInterest != _networkManager.LocalNwkAddress &&
                    !ZigBeeBroadcastDestination.IsBroadcast(matchRequest.NwkAddrOfInterest))
                {
                    Log.Debug("{ExtPanId}: ClusterMatcher no match to local address", _networkManager.ZigBeeExtendedPanId);
                    return;
                }

                // We want to match any of our local servers (ie our input clusters) with any
                // requested clusters in the requests cluster list
                if (matchRequest.InClusterList.Intersect(_serverClusters).Count() == 0 &&
                    matchRequest.OutClusterList.Intersect(_clientClusters).Count() == 0)
                {
                    Log.Debug("{ExtPanId}: ClusterMatcher no match", _networkManager.ZigBeeExtendedPanId);
                    return;
                }

                MatchDescriptorResponse matchResponse = new MatchDescriptorResponse();
                matchResponse.Status = ZdoStatus.SUCCESS;
                List <byte> matchList = new List <byte>();
                matchList.Add(_localEndpointId);
                matchResponse.MatchList          = matchList;
                matchResponse.NwkAddrOfInterest  = _networkManager.LocalNwkAddress;
                matchResponse.TransactionId      = matchRequest.TransactionId;
                matchResponse.DestinationAddress = command.SourceAddress;
                Log.Debug("{ExtPanId}: ClusterMatcher sending match {Response}", _networkManager.ZigBeeExtendedPanId, matchResponse);
                _networkManager.SendCommand(matchResponse);
            }
        }
Пример #5
0
        /// <summary>
        /// Sends ZigBeeCommand command and uses the ZigBeeTransactionMatcher to match the response.
        /// The task will be timed out if there is no response.
        ///
        /// <param name="command">the ZigBeeCommand</param>
        /// <param name="responseMatcher">the ZigBeeTransactionMatcher</param>
        /// </summary>
        public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher)
        {
            CommandResult commandResult;

            lock (_objLock)
            {
                _command         = command;
                _responseMatcher = responseMatcher;
                _networkManager.AddCommandListener(this);

                int transactionId = _networkManager.SendCommand(command);

                if (command is ZclCommand cmd)
                {
                    cmd.TransactionId = (byte)transactionId;
                }
                //Without RunContinuationsAsynchronously, calling SetResult can block the calling thread, because the continuation is run synchronously
                //see https://stackoverflow.com/a/37492081
                _sendTransactionTask = new TaskCompletionSource <CommandResult>(TaskCreationOptions.RunContinuationsAsynchronously);
            }

            var t           = _sendTransactionTask.Task;
            var cancel      = new CancellationTokenSource();
            var timeoutTask = Task.Delay(Timeout, cancel.Token);

            if (t == await Task.WhenAny(t, timeoutTask).ConfigureAwait(false))
            {
                cancel.Cancel(); //Cancel the timeout task
                commandResult = t.Result;
            }
            else
            {
                /* Timeout */
                Log.Debug("Transaction timeout: {Command}", _command);
                commandResult = new CommandResult();
            }
            _networkManager.RemoveCommandListener(this);

            return(commandResult);
        }
Пример #6
0
        /// <summary>
        /// Sends ZigBeeCommand command and uses the ZigBeeTransactionMatcher to match the response.
        /// The task will be timed out if there is no response.
        ///
        /// <param name="command">the ZigBeeCommand</param>
        /// <param name="responseMatcher">the ZigBeeTransactionMatcher</param>
        /// </summary>
        public async Task <CommandResult> SendTransaction(ZigBeeCommand command, IZigBeeTransactionMatcher responseMatcher)
        {
            _command         = command;
            _responseMatcher = responseMatcher;
            _timeout         = DateTime.Now.AddMilliseconds(DEFAULT_TIMEOUT_MILLISECONDS);

            _networkManager.AddCommandListener(this);

            int transactionId = _networkManager.SendCommand(command);

            if (command is ZclCommand cmd)
            {
                cmd.TransactionId = (byte)transactionId;
            }

            _sendTransactionTask = new TaskCompletionSource <CommandResult>();
            var t           = _sendTransactionTask.Task;
            var timeoutTask = Task.Delay(DEFAULT_TIMEOUT_MILLISECONDS);
            var cancel      = new CancellationTokenSource();

            if (t == await Task.WhenAny(t, timeoutTask).ConfigureAwait(false))
            {
                cancel.Cancel(); //Cancel the timeout task
                _networkManager.RemoveCommandListener(this);
                return(t.Result);
            }
            else
            {
                /* Timeout */
                Log.Debug("Transaction timeout: {Command}", _command);

                _networkManager.RemoveCommandListener(this);

                return(new CommandResult());
            }

            /* !!! OLD CODE WITHOUT COMPLETION SOURCE - DO NOT DELET IT YET !!!
             *
             * return await Task.Run(() =>
             * {
             *  while (true)
             *  {
             *      if (DateTime.Now < _timeout)
             *      {
             *          if (_result != null)
             *          {
             *              return _result;
             *          }
             *      }
             *      else
             *      {
             *          Log.Debug("Transaction timeout: {Command}", _command);
             *          lock (_command)
             *          {
             *              _networkManager.RemoveCommandListener(this);
             *              return new CommandResult();
             *          }
             *      }
             *  }
             * });
             *
             */
        }