예제 #1
0
        private async Task <IXBeeResponse> SendCommandAsync(IXBeeCommand command, CancellationToken cancellationToken)
        {
            IXBeeListener xbeeListener = new XBeeListener();

            AddTransactionListener(xbeeListener);
            lock (_frameIdLock)
            {
                xbeeListener.OurFrameId = Interlocked.Increment(ref _frameId);
                command.SetFrameId(xbeeListener.OurFrameId);
                Interlocked.CompareExchange(ref _frameId, 1, 256);
            }

            // Send the transaction
            QueueFrame(command);

            while (!_mainCancellationToken.IsCancellationRequested &&
                   !cancellationToken.IsCancellationRequested &&
                   !xbeeListener.Complete)
            {
                // wait until transaction is complete
                await Task.Delay(5);
            }
            RemoveTransactionListener(xbeeListener);
            return(xbeeListener.CompletionResponse);
        }
예제 #2
0
        /// <summary>
        /// Sends a XBee request to the NCP without waiting for the response.
        /// </summary>
        /// <param name="command">Request <see cref="IXBeeCommand"/> to send.</param>
        /// <returns></returns>
        public async Task <IXBeeResponse> SendRequestAsync(IXBeeCommand command)
        {
            IXBeeListener xbeeListener = new XBeeListener();

            await _taskFactory.StartNew(() =>
            {
                AddTransactionListener(xbeeListener);
                lock (_frameIdLock)
                {
                    xbeeListener.OurFrameId = Interlocked.Increment(ref _frameId);
                    command.SetFrameId(xbeeListener.OurFrameId);
                    Interlocked.CompareExchange(ref _frameId, 1, 256);
                }

                // Send the transaction
                QueueFrame(command);

                lock (xbeeListener)
                {
                    while (!xbeeListener.Complete)
                    {
                        // wait until transaction is complete
                    }
                }
                RemoveTransactionListener(xbeeListener);
            });

            return(xbeeListener.CompletionResponse);
        }
예제 #3
0
        /// <summary>
        /// Add a XBee command frame to the send queue.The sendQueue is a FIFO queue.
        /// This method queues a <see cref="IXBeeCommand"/>
        /// frame without waiting for a response.
        /// </summary>
        private void QueueFrame(IXBeeCommand request)
        {
            _sendQueue.Enqueue(request);

            Log.Verbose($"TX XBEE queue: {_sendQueue.Count}: {request}");

            SendNextFrame();
        }
예제 #4
0
 /// <summary>
 /// Cancel the transaction and send the next frame from the queue.
 /// We don't try and retry as this might cause other unwanted issues.
 /// </summary>
 private void TimeoutCallback(object state)
 {
     StopTimer();
     Log.Debug("XBEE Timer: Timeout");
     lock (_commandLock)
     {
         if (_sentCommand != null)
         {
             _sentCommand = null;
             SendNextFrame();
         }
     }
 }
예제 #5
0
        private void SendNextFrame()
        {
            // Are we already processing a command?
            if (_sentCommand != null)
            {
                Log.Debug($"TX XBEE Frame outstanding: {_sentCommand}");
                return;
            }

            bool isFrameDequeuedSuccsess = _sendQueue.TryDequeue(out IXBeeCommand nextFrame);

            if (!isFrameDequeuedSuccsess)
            {
                Log.Verbose("XBEE TX: Nothing to send");
                // Nothing to send
                StopTimer();
                return;
            }

            Log.Debug($"TX XBEE: {nextFrame}");

            // Remember the command we're processing
            _sentCommand = nextFrame;

            // Send the data
            List <byte> bytes = new List <byte>();

            bytes.Add(XBEE_FLAG);
            StringBuilder builder = new StringBuilder();

            int[] frames = nextFrame.Serialize();
            foreach (int sendByte in frames)
            {
                builder.Append(string.Format(" 0x{0:X2}", sendByte));
                if (_escapeCodes.Contains((byte)sendByte))
                {
                    bytes.Add(XBEE_ESCAPE);
                    bytes.Add((byte)(sendByte ^ XBEE_XOR));
                }
                else
                {
                    bytes.Add((byte)sendByte);
                }
            }
            Log.Verbose($"TX XBEE Data:{builder.ToString()}");
            _serialPort.Write(bytes.ToArray());

            // Start the timeout
            Log.Verbose("XBEE Timer: Start");
            _timeoutTimer.Change(_commandTimeout, Timeout.Infinite);
        }
예제 #6
0
        /// <summary>
        /// Sends a XBee request to the dongle and waits for the response.The response is correlated with the request
        /// and the response data is returned as a <see cref="IXBeeEvent"/>.
        /// </summary>
        /// <param name="command">Request <see cref="IXBeeCommand"/> to send</param>
        /// <returns>Response <see cref="IXBeeResponse"/> the response, or null if there was a timeout</returns>
        public IXBeeResponse SendRequest(IXBeeCommand command)
        {
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken       cancellationToken       = cancellationTokenSource.Token;

            Task <IXBeeResponse> sendCommandTask = SendCommandAsync(command, cancellationToken);
            bool taskResult = sendCommandTask.Wait(_transactionTimeout);

            if (taskResult)
            {
                return(sendCommandTask.Result);
            }
            else
            {
                Log.Debug($"XBee interrupted in SendRequest {command}");
                cancellationTokenSource.Cancel();
                return(null);
            }
        }
예제 #7
0
        /// <summary>
        /// Construct which sets input stream where the packet is read from the and
        /// handler which further processes the received packet.
        /// </summary>
        /// <param name="serialPort">The serial port.</param>
        public void Start(IZigBeePort serialPort)
        {
            Interlocked.Exchange(ref _frameId, 1);

            _serialPort   = serialPort;
            _timeoutTimer = new Timer(new TimerCallback(TimeoutCallback));
            // TODO af: find the equivalent in C# --> maybe ThreadPool-Class is the right one
            //timeoutScheduler = Executors.newSingleThreadScheduledExecutor();

            // Clear anything in the receive buffer before we start
            EmptyRxBuffer();

            // TODO af: find a more elegant way to solve this --> maybe async/await
            // This might be resolved with a TaskCompletionSource
            // See the refactored while loop in ZigBeeTransaction.cs line 84
            _parserThread = _taskFactory.StartNew(() =>
            {
                Log.Debug("XBeeFrameHandler task started.");
                while (!_closeHandler)
                {
                    try
                    {
                        lock (_commandLock)
                        {
                            if (_sentCommand == null)
                            {
                                SendNextFrame();
                            }
                        }

                        // Get a packet from the serial port
                        int[] responseData = GetPacket();
                        if (responseData == null)
                        {
                            lock (_commandLock)
                            {
                                _sentCommand = null;
                            }
                            continue;
                        }

                        StringBuilder builder = new StringBuilder();
                        foreach (int value in responseData)
                        {
                            builder.Append(string.Format(" 0x{0:X2}", value.ToString()));
                        }
                        Log.Verbose($"RX XBEE Data: {builder}");

                        // Use the Event Factory to get an event
                        IXBeeEvent xBeeEvent = XBeeEventFactory.GetXBeeFrame(responseData);
                        if (xBeeEvent != null)
                        {
                            NotifyEventReceived(xBeeEvent);
                        }

                        // Use the Response Factory to get a response
                        IXBeeResponse response = XBeeResponseFactory.GetXBeeFrame(responseData);
                        if (response != null && NotifyResponseReceived(response))
                        {
                            lock (_commandLock)
                            {
                                _sentCommand = null;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "XBeeFrameHandler exception {Exception}", ex.Message);
                    }
                }
                Log.Debug("XBeeFrameHandler thread exited.");
            });
        }
예제 #8
0
 /// <summary>
 /// Sends a XBee request to the NCP without waiting for the response.
 /// </summary>
 /// <param name="command">Request <see cref="IXBeeCommand"/> to send.</param>
 /// <returns></returns>
 public Task <IXBeeResponse> SendRequestAsync(IXBeeCommand command)
 {
     return(_taskFactory.StartNew(() => SendRequest(command)));
 }