gusucode.com > vnt工具箱matlab源码程序 > vnt/vnt/+j1939/TPReceiver.m

    classdef TPReceiver < handle
% TPReceiver Class that implements an active J1939 transport protocol connection.
%
%   This class is used to implement the J1939 transport protocol. A single
%   object of this class represents a single transport protocol transfer
%   sequence happening on the network. It stores information about that
%   transfer and collects the data messages until the sequence is complete.
%   Once complete, the class builds a final parameter group objects for the
%   reconstituted data. 

% Authors: Jaremy Pyle
% Copyright 2015 The MathWorks, Inc.

properties (SetAccess = 'private')
    % State - The current state of the transport protocol data transfer.
    State
    % PGN - The parameter group number to apply to the reconstructed 
    % parameter group.
    PGN
    % Priority - The priority to apply to the reconstructed parameter group.
    Priority
    % SourceAddress - The source address to apply to the reconstructed 
    % parameter group.
    SourceAddress
    % DestinationAddress - The destintation address to apply to the 
    % reconstructed parameter group.    
    DestinationAddress
    % PDUFormatType - The J1939 protocol data unit format of this 
    % parameter group.
    PDUFormatType
    % Size - The size in bytes of the full data transfer.
    Size
    % Packets - The number of data transfer packets to expect.
    Packets
    % DataTransferBuffer - A array of data transfer packets collected as
    % the information comes in from the network.
    DataTransferBuffer
    % PacketReceiveStatus - An array of boolean values used to keep track
    % of which data transfer packets were received.
    PacketReceiveStatus
    % NextSequenceNumber - The next expected sequence number to be received
    % for a transport protocol sequence.
    NextSequenceNumber
    % CompletePG - The final j1939.ParameterGroup object representing the
    % complete data transfer.
    CompletePG
    % Database - A can.Database object containing the definition of the
    % final parameter group.
    Database
    % BroadcastT1Time - Measures elapsed time from DT to DT in a broadcast
    % sequence.
    BroadcastT1Time
end

methods
   
    function obj = TPReceiver(database, newCM)
    % TPReceiver Class constructor.
    
        % Store the provided database.
        obj.Database = database;
        
        % Get the individual parameter elements from the identifier.
        [priority, sourceAddress, destinationAddress, ~] = ...
            mexJ1939Utility('getSubsetForConstruction', newCM.ID);        

        % Set the PG details.
        obj.PGN = typecast([newCM.Data(6:8) uint8(0)], 'uint32');
        obj.Priority = priority;
        obj.SourceAddress = sourceAddress;
        obj.DestinationAddress = destinationAddress;
        obj.PDUFormatType = newCM.Data(7);
        
        % Get the size of the multiframe transfer.
        obj.Size = typecast(newCM.Data(2:3), 'uint16');
        
        % Get the number of expected packats for the multiframe transfer.
        obj.Packets = newCM.Data(4);
        
        % Clear the data buffer to be ready for new packets.
        obj.DataTransferBuffer = struct('ID', [], 'Data', [], ...
            'Timestamp', [], 'Extended', [], 'Remote', [], ...
            'Error', [], 'PGN', []);
        obj.PacketReceiveStatus = false([1, obj.Packets]);
        obj.CompletePG = [];
        
        % Set the state to actively building a multiframe result.
        obj.State = j1939.TPRxState.Acquiring;
        
        % Set the initial expected sequence number.
        obj.NextSequenceNumber = 1;

        % Set broadcast properties.
        if obj.isBroadcast()
            % Start timeout timing.
            obj.BroadcastT1Time = tic;
        end
    end
    
    function processCTS(obj, newCTS)
    % processCTS Process TP Clear To Send messages.
    %
    %   This method is used to manage clear to send messages for this
    %   multiframe reception.
    
        % If the sequence has failed, do nothing.
        if obj.State == j1939.TPRxState.Failed
            return;
        end
        
        % Set the next expected sequence number from the message input.
        obj.NextSequenceNumber = newCTS.Data(3);
    end    

    function processDT(obj, newDT)
    % processDT Process TP Data Transfer messages.
    %
    %   This method is used to manage data transfer messages for this
    %   multiframe reception. It adds the input DT message to the collected
    %   incoming data.
    
        % If the sequence has failed, do nothing.
        if obj.State == j1939.TPRxState.Failed
            return;
        end
        
        % Ensure proper timeout monitoring for broadcast sequences.
        if obj.isBroadcast()
            % Check the elapsed time since the last TP message for this
            % broadcast sequence.
            if toc(obj.BroadcastT1Time) > j1939.Utility.TPTimeoutT1
                % Fail this sequence due to the T1 timeout.
                obj.State = j1939.TPRxState.Failed;
            end
        end
        
        % Check that the new data transfer message has the expected
        % sequence numbering.
        if obj.NextSequenceNumber ~= newDT.Data(1)
            % Fail this sequence due to an out of sequence error.
            obj.State = j1939.TPRxState.Failed;
        end
        
        % Add this new data transfer to the data buffer taking care to
        % append properly to avoid any warnings or errors. We use the
        % sequence number of the DT message as the array index into the
        % holding buffer. This ensures that as messages arrive, they are
        % placed exactly in proper sequence.
        obj.DataTransferBuffer(newDT.Data(1)) = newDT;
        % Note that this packet in the sequence was received.
        obj.PacketReceiveStatus(newDT.Data(1)) = true;
        
        % If this is a broadcast, check for completion of the sequence.
        % Peer-to-peer sequences are completed via a CM acknowledgment. 
        if obj.isBroadcast()
            % Make sure we have all of the packets for this broadcast.
            if all(obj.PacketReceiveStatus)
                obj.completeParameterGroup();
            else
                % Reset the time counter.
                obj.BroadcastT1Time = tic;
            end
        end
        
        % Increment the next sequence number.
        obj.NextSequenceNumber = obj.NextSequenceNumber + 1;
    end
    
    function completeParameterGroup(obj, varargin)
    % completeParameterGroup Reconstruct a received multiframe parameter group.
    %
    %   This method is used upon completed reception of all of the data
    %   transfer messages of a multiframe sequence. It builds the final
    %   singular parameter group out of the multiframe data.
        
        % If the sequence has failed, do nothing.
        if obj.State == j1939.TPRxState.Failed
            return;
        end
        
        % Check if all data transfers for this sequence have been received.
        if ~all(obj.PacketReceiveStatus)
            % If not, then exit.
            obj.State = j1939.TPRxState.Failed;
            return;
        end
        
        % Save the PGN.
        obj.CompletePG.PGN = obj.PGN;
        
        % Build the identifier.
        obj.CompletePG.ID = uint32(0);
        obj.CompletePG.ID = j1939.Utility.setPDUField( ...
            'Priority', obj.Priority, obj.CompletePG.ID);
        obj.CompletePG.ID = j1939.Utility.setPDUField( ...
            'PGN', obj.PGN, obj.CompletePG.ID);
        if obj.PDUFormatType < j1939.Utility.PDUFormatThreshold
            obj.CompletePG.ID = j1939.Utility.setPDUField( ...
                'PDUSpecific', obj.DestinationAddress, obj.CompletePG.ID);
        end
        obj.CompletePG.ID = j1939.Utility.setPDUField( ...
            'SourceAddress', obj.SourceAddress, obj.CompletePG.ID);
        
        % Set the fixed elements.
        obj.CompletePG.Extended = true;
        obj.CompletePG.Error = false;
        obj.CompletePG.Remote = false;
        
        % Load the data.
        newData = [];
        for ii = 1:obj.Packets
            newData = [newData obj.DataTransferBuffer(ii).Data(2:end)]; %#ok<AGROW>
        end
        % Remove any fill bytes.
        newData(obj.Size+1:end) = [];
        % Store the final data array.
        obj.CompletePG.Data = newData;

        % Set the timestamp depending on the type of transfer.
        if obj.isBroadcast()
            % Set the timestamp of the final PG to the latest timestamp of all
            % of the data transfer messages for a broadcast.
            obj.CompletePG.Timestamp = max([obj.DataTransferBuffer.Timestamp]);      
        else
            % For a peer-to-peer transfer, use the timestamp from the
            % acknowledgment CM.
            obj.CompletePG.Timestamp = varargin{1};
        end
        
        % Mark the state as complete.
        obj.State = j1939.TPRxState.Completed;
    end
    
    function out = isComplete(obj)
    % isComplete Check if the multiframe reception sequence is complete.
    %
    %   This method is used to check if the multiframe message sequence for
    %   the transfer represented by this object is complete. It returns a
    %   boolean state result.
        
        % Return true of this multiframe packet sequence is complete and
        % the data is fully reconstituted.
        if obj.State == j1939.TPRxState.Completed
            out = true;
        else
            out = false;
        end
    end
    
    function out = isBroadcast(obj)
    % isBroadcast Check if the multiframe reception sequence is broadcast.
    %
    %   This method is used to check if the multiframe message sequence for
    %   the transfer represented by this object is of broadcast or
    %   peer-to-peer type. It returns a boolean state result.
        
        if obj.DestinationAddress == j1939.Utility.DestinationAll
            out = true;
        else
            out = false;
        end
    end
    
end   
    
end