Exemple #1
0
        /// <summary>
        ///     Read from serial provider with retry
        /// </summary>
        /// <returns>Data from port or null on error</returns>
        private byte[] TryPortRead()
        {
            var backoff = TimeSpan.Zero;
            var retry   = 3;

            byte[] deviceData;
            do
            {
                // Device always responds with 11 bytes
                deviceData = SerialProvider.Read(11);

                if (backoff != TimeSpan.Zero)
                {
                    Thread.Sleep(backoff);
                }

                backoff += TimeSpan.FromMilliseconds(50);
            } while (deviceData is null && retry-- > 0);

            return(deviceData);
        }
Exemple #2
0
        /// <summary>
        ///     Send poll message to device and return a validated response.
        ///     If the response is malformed, null will be returned.
        /// </summary>
        /// <returns>Device response</returns>
        private ApexResponseMessage SendPollMessage()
        {
            // Replay the last message or build a new message
            var nextMessage = _apexState.LastMessage ?? GetNextHostMessage();
            var payload     = nextMessage.Serialize();

            SerialProvider.Write(payload);

            // Device always responds with 11 bytes
            var deviceData   = TryPortRead();
            var pollResponse = new ApexResponseMessage(deviceData);

            // Log the parsed command and response together for easier analysis
            Logger?.Trace("{0} poll message: {1}", GetType().Name, nextMessage);
            Logger?.Trace("{0} poll response: {1}", GetType().Name, pollResponse);

            // The response was invalid or incomplete
            if (!pollResponse.IsValid)
            {
                // Request retransmission (by not modifying the ACK and payload)
                _apexState.LastMessage = nextMessage;

                // Update counter for responsive check
                if (pollResponse.IsEmptyResponse)
                {
                    _apexState.NonResponsiveCount++;
                }

                // If there is a protocol violation and strict mode is enabled,
                // report the problem and request a retransmit
                if (pollResponse.HasProtocolViolation && Config.StrictMode)
                {
                    Logger?.Error("{0} Invalid message: {1}", GetType().Name, deviceData.ToHexString());
                    Logger?.Error("{0} Problems: {1}", GetType().Name,
                                  string.Join(Environment.NewLine, pollResponse.AllPacketIssues));
                    return(null);
                }

                // Target is responsive, this is just a bad message
                if (!IsUnresponsive)
                {
                    return(null);
                }

                // Target is unresponsive, check if client needs to be notified
                if (!_apexState.NotifiedLostConnection)
                {
                    LostConnection();

                    _apexState.NotifiedLostConnection = true;
                }

                Logger?.Trace("{0} Device is not responding", GetType().Name);

                return(null);
            }

            // If ACK does not match, then device is requesting a retransmit
            if (nextMessage.Ack != pollResponse.Ack)
            {
                // Request retransmission
                _apexState.LastMessage = nextMessage;

                return(null);
            }

            // Update state with successful polling notification
            _apexState.RegisterSuccessfulPoll();

            return(pollResponse);
        }