www.gusucode.com > vnt工具箱matlab源码程序 > vnt/vnt/+can/+kvaser/Channel.m
classdef Channel < can.Channel % Channel Connection to a Kvaser CAN device channel. % % The Channel class provides connectivity to CAN channels for Kvaser % devices. It contains properties and methods to configure and use the % channel on a network. % % See also VNT. % Authors: JDP % Copyright 2009-2015 The MathWorks, Inc. % Note that all uncommented properties are Abstract and inherit their % help from the super class. properties (SetAccess = 'private', GetAccess = 'protected') AsyncioChannel AsyncioReplayChannel end properties (Dependent, SetAccess = 'private') % BusLoad - The utilization level of the bus as a percentage. BusLoad end properties (Dependent, SetAccess = 'private') BusSpeed NumOfSamples SJW TSEG1 TSEG2 end properties (Dependent, SetAccess = 'private') BusStatus end properties (SetAccess = 'private') Device DeviceChannelIndex DeviceSerialNumber DeviceVendor end properties (SetAccess = 'private', GetAccess = 'private') % DeviceCode - The vendor specific code for the connected device. DeviceCode % DeviceIndex - A numeric index to the connected devices used to % address the proper one if more than one of the same device are % connected. This value is parsed out of Device and stored % separately for easier internal access. DeviceIndex end properties (SetAccess = 'private', GetAccess = 'private') % Handle - The handle value used for access within the Kvaser % driver to access the device represented by the channel. Handle end properties (SetAccess = 'protected') InitializationAccess InitialTimestamp end properties (Dependent, SetAccess = 'private') ReceiveErrorCount TransmitErrorCount end properties (SetAccess = 'private', GetAccess = 'protected') ReceiveQueueSize TransmitQueueSize end properties (Dependent) SilentMode end properties (Dependent, SetAccess = 'private') TransceiverName end properties (Dependent) TransceiverState end properties (SetAccess = 'private', GetAccess = 'protected') MultipleAccessAllowed = true; Usable = false; end properties UserData end methods function obj = Channel(varargin) % Channel Construct a connection to a Kvaser CAN device. % Check the argument count. narginchk(3,3); % Put the input arguments into local variables. inVendor = varargin{1}; inDevice = varargin{2}; inDeviceChannelIndex = varargin{3}; % Validate the device string. validateattributes(inDevice, {'char'}, ... {'nonempty', 'row'}, 'Channel', 'DEVICE'); % Parse the individual pieces of the device string. deviceParts = textscan(inDevice, '%s'); deviceParts = cat(1, deviceParts{:})'; deviceIndex = str2double(deviceParts{end}); % Validate the device index piece of the device string. try validateattributes(deviceIndex, ... {'numeric'}, ... {'finite', 'integer', 'nonempty', 'nonnan', ... 'nonsparse', 'positive', 'real', 'scalar'}); catch err %#ok<NASGU> error(message('vnt:Channel:InvalidDeviceIndex')); end % Validate the device channel index. validateattributes(inDeviceChannelIndex, ... {'numeric'},... {'finite', 'integer', 'nonempty', 'nonnan', ... 'nonsparse', 'positive', 'real', 'scalar'}, ... 'Channel', 'DEVICECHANNELINDEX'); % Put the device name back together, but leave off the last % entry of the string which is the device index. deviceName = deviceParts{1}; for ii = 2:(numel(deviceParts) - 1) deviceName = [deviceName ' ' deviceParts{ii}]; %#ok<AGROW> end % Verify if the requested device is supported by the toolbox. if ~can.kvaser.Utility.isDeviceSupported(deviceName) error(message('vnt:Channel:UnsupportedDevice')); end % Set the device identification properties. obj.DeviceVendor = inVendor; obj.DeviceChannelIndex = inDeviceChannelIndex; deviceName = can.kvaser.Utility.translateDeviceName(deviceName); obj.Device = [deviceName ' ' num2str(deviceIndex)]; obj.DeviceIndex = deviceIndex; obj.DeviceCode = can.kvaser.Utility.translateDeviceCode(deviceName); % Open the vendor library. can.kvaser.CANLib.canInitializeLibrary(); % Get channel data for this device and channel. channelData = can.kvaser.Utility.getDriverData(... obj.DeviceCode,... obj.DeviceIndex,... obj.DeviceChannelIndex); if isempty(channelData) error(message('vnt:Channel:DeviceNotFound')); end % Set the device serial number. obj.DeviceSerialNumber = channelData.CardSerialNumber; % Get a handle to the device channel. [obj.Handle, obj.InitializationAccess] = ... can.kvaser.CANLib.canOpenChannel(channelData.ChannelNumber); % Set for proper timestamp scaling for received messages. can.kvaser.CANLib.canIoCtl(obj.Handle, 6, 1); % Turn on reception of messages by this channel for messages % sent by this channel. can.kvaser.CANLib.canIoCtl(obj.Handle, 7, 1); % Turn on advanced access error reporting. can.kvaser.CANLib.canIoCtl(obj.Handle, 20, 1); % Set the queue sizes. obj.ReceiveQueueSize = 1024; obj.TransmitQueueSize = 256; % Determine the path for all asyncio plugins. arch = computer('arch'); devicePath = fullfile(toolboxdir('vnt'), 'vnt', 'private', arch, 'kvasercanlibplugin'); converterPath = fullfile(toolboxdir('vnt'), 'vnt', 'private', arch, 'canmlconverter'); % Create the asyncio object for normal receive and transmit. asyncioOptions.Handle = obj.Handle; asyncioOptions.ReceiveCapable = true; asyncioOptions.TransmitCapable = true; asyncioOptions.ReplayCapable = false; obj.AsyncioChannel = asyncio.Channel( ... devicePath, converterPath, asyncioOptions, [Inf, 0]); % Create the asyncio replay object. asyncioOptions.ReceiveCapable = false; asyncioOptions.TransmitCapable = true; asyncioOptions.ReplayCapable = true; obj.AsyncioReplayChannel = asyncio.Channel( ... devicePath, converterPath, asyncioOptions, [Inf, Inf]); % Set the object usable. obj.Usable = true; end function configBusSpeed(obj, varargin) % configBusSpeed Set the bit timing of a CAN channel. % % configBusSpeed(CHANNEL, BUSSPEED) sets the speed of the CHANNEL % to BUSSPEED in a direct form that uses default bit timing % calculation factors. % % configBusSpeed(CHANNEL, BUSSPEED, SJW, TSEG1, TSEG2, NUMBEROFSAMPLES) % sets the speed of the CHANNEL to BUSSPEED using specified bit % timing calculation factors in an advanced form. % % Inputs: % BUSSPEED - The speed of a network in bits per second. % SJW - The Synchronization Jump Width which helps define the % length of a bit on a network. % TSEG1 - Time Segment 1 which defines the section before % a bit is sampled on a network. % TSEG2 - Time Segment 2 which defines the section after % a bit is sampled on a network. % NUMBEROFSAMPLES - The count of samples used for determining % the bit state of a network. % % Note that unless you have specific timing requirements provided % for your network, it is recommended to use the direct form of % configBusSpeed. Also note that bit timing can only be set when % the channel is offline and has initialization access to the device. % % Examples: % channel = canChannel('Kvaser', 'USBcan Professional 1', 1) % configBusSpeed(channel, 250000) % % channel = canChannel('Kvaser', 'USBcan Professional 1', 1) % configBusSpeed(channel, 500000, 1, 4, 3, 1) % % See also VNT. % Check the argument count. if ((nargin ~= 2) && (nargin ~= 6)) error(message('vnt:Channel:IncorrectArgumentCount')); end % Validate the channel before using its functionality. assertValidity(obj); % Check if the channel has initialization access. if ~obj.InitializationAccess error(message('vnt:Channel:NoInitAccessToChannel')); end % Verify that the channel is offline. if obj.Running error(message('vnt:Channel:ChannelNotOffline')); end % Validate the busSpeed. validateattributes(varargin{1}, ... {'numeric'}, ... {'integer', 'nonempty', 'nonnan', 'nonsparse', 'real', ... 'scalar', '>=', 8000, '<=', 1000000}, ... 'configBusSpeed', 'BUSSPEED'); % Set the bit timing in direct form by only providing the bus % speed when two arguments are provided. if nargin == 2 % Set the bit timing in direct form. can.kvaser.CANLib.canSetBitrate(obj.Handle, varargin{1}); % Set the bit timing in advanced form by providing calculation % factors when six arguments are provided. elseif nargin == 6 % Validate the other input arguments. validateattributes(varargin{2}, {'numeric'}, ... {'finite', 'integer', 'nonempty', 'nonnan', ... 'nonnegative', 'nonsparse', 'real', 'scalar'}, ... 'configBusSpeed', 'SJW'); validateattributes(varargin{3}, {'numeric'}, ... {'finite', 'integer', 'nonempty', 'nonnan', ... 'nonnegative', 'nonsparse', 'real', 'scalar'}, ... 'configBusSpeed', 'TSEG1'); validateattributes(varargin{4}, {'numeric'}, ... {'finite', 'integer', 'nonempty', 'nonnan', ... 'nonnegative', 'nonsparse', 'real', 'scalar'}, ... 'configBusSpeed', 'TSEG2'); validateattributes(varargin{5}, {'numeric'}, ... {'finite', 'integer', 'nonempty', 'nonnan', ... 'nonnegative', 'nonsparse', 'real', 'scalar'}, ... 'configBusSpeed', 'NUMOFSAMPLES'); % The Kvaser CANLib currently does not perform adequate % validation on advanced bus speed settings. When setting % in advanced mode, we want to first set the bus speed in % direct form and use that operation to validate the bus % speed value. Once proper validation is done in their % driver, this extra validation on our part can be removed. can.kvaser.CANLib.canSetBitrate(obj.Handle, varargin{1}); % Set the bit timing in advanced form. can.kvaser.CANLib.canSetBusParams(obj.Handle, ... varargin{1},... % Bus speed. varargin{3},... % TSEG1. varargin{4},... % TSEG2. varargin{2},... % SJW. varargin{5}); % Number of samples. end end function disp(obj) % Validate the channel before using its functionality. assertValidity(obj); % Display a top level summary. fprintf(1, 'Summary of CAN Channel using ''%s'' ''%s'' Channel %d.\n\n',... obj.DeviceVendor,... obj.Device,... obj.DeviceChannelIndex); % Display basic configuration parameters. fprintf(1, ' Channel Parameters: Bus Speed is %d.\n', obj.BusSpeed); fprintf(1, '%23sBus Status is ''%s''.\n', '', obj.BusStatus); fprintf(1, '%23sTransceiver name is ''%s''.\n', '', obj.TransceiverName); fprintf(1, '%23sSerial Number of this device is %d.\n', '', obj.DeviceSerialNumber); % Display the initialization access status. if obj.InitializationAccess fprintf(1, '%23sInitialization access is allowed.\n', ''); else fprintf(1, '%23sInitialization access is not allowed.\n', ''); end % Display the currently attached database. if isempty(obj.Database) fprintf(1, '%23sNo database is attached.\n\n', ''); else fprintf(1, '%23s''%s.dbc'' database is attached.\n\n', '', obj.Database.Name); end % Display the current channel status. if obj.Running fprintf(1, '%14sStatus: Online.\n', ''); fprintf(1, '%23s%3.2f%% Bus Load.\n', '', obj.BusLoad); else fprintf(1, '%14sStatus: Offline - Waiting for start.\n', ''); end % Display message transmit and receive information. fprintf(1, '%23s%d messages available to receive.\n', '', obj.MessagesAvailable); fprintf(1, '%23s%d messages transmitted since last start.\n', '', obj.MessagesTransmitted); fprintf(1, '%23s%d messages received since last start.\n\n', '', obj.MessagesReceived); % Display a filter history section with the first entry in the log. fprintf(1, ' Filter History: %s\n', obj.FilterHistory); % Add a final line for spacing. fprintf(1, '\n'); end function getdisp(obj) % Validate the channel before using its functionality. assertValidity(obj); % Display general information. fprintf(1, '\n General Settings:\n'); fprintf(1, '\tBusLoad = %3.2f\n', obj.BusLoad); fprintf(1, '\tBusStatus = ''%s''\n', obj.BusStatus); if isempty(obj.Database) fprintf(1, '\tDatabase = []\n'); else fprintf(1, '\tDatabase = ''%s.dbc''\n', obj.Database.Name); end fprintf(1, '\tFilterHistory = ''%s''\n', obj.FilterHistory); fprintf(1, '\tInitializationAccess = %d\n', obj.InitializationAccess); fprintf(1, '\tMessageReceivedFcn = %s\n', can.Utility.callbackFcnToString(obj.MessageReceivedFcn)); fprintf(1, '\tMessageReceivedFcnCount = %d\n', obj.MessageReceivedFcnCount); fprintf(1, '\tMessagesAvailable = %d\n', obj.MessagesAvailable); fprintf(1, '\tMessagesReceived = %d\n', obj.MessagesReceived); fprintf(1, '\tMessagesTransmitted = %d\n', obj.MessagesTransmitted); fprintf(1, '\tReceiveErrorCount = %d\n', obj.ReceiveErrorCount); fprintf(1, '\tRunning = %d\n', obj.Running); fprintf(1, '\tSilentMode = %d\n', obj.SilentMode); fprintf(1, '\tTransmitErrorCount = %d\n', obj.TransmitErrorCount); % Display device specific information. fprintf(1, '\n Device Settings:\n'); fprintf(1, '\tDevice = ''%s''\n', obj.Device); fprintf(1, '\tDeviceChannelIndex = %d\n', obj.DeviceChannelIndex); fprintf(1, '\tDeviceSerialNumber = %d\n', obj.DeviceSerialNumber); fprintf(1, '\tDeviceVendor = ''%s''\n', obj.DeviceVendor); % Display transceiver information. fprintf(1, '\n Transceiver Settings:\n'); fprintf(1, '\tTransceiverName = ''%s''\n', obj.TransceiverName); fprintf(1, '\tTransceiverState = %d\n', obj.TransceiverState); % Display bit timing information. fprintf(1, '\n Bit Timing Settings:\n'); fprintf(1, '\tBusSpeed = %d\n', obj.BusSpeed); fprintf(1, '\tSJW = %d\n', obj.SJW); fprintf(1, '\tTSEG1 = %d\n', obj.TSEG1); fprintf(1, '\tTSEG2 = %d\n', obj.TSEG2); fprintf(1, '\tNumOfSamples = %d\n\n', obj.NumOfSamples); end function setdisp(obj) % Validate the channel before using its functionality. assertValidity(obj); fprintf(1, '\n Database = can.Database handle -or- empty\n'); fprintf(1, ' MessageReceivedFcn = string -or- function handle -or- cell array\n'); fprintf(1, ' MessageReceivedFcnCount\n'); fprintf(1, ' SilentMode = [ {false} | true ]\n'); fprintf(1, ' TransceiverState\n\n'); end function out = get.BusLoad(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Request the status from the driver. can.kvaser.CANLib.canRequestBusStatistics(obj.Handle); % Read the status from the driver. busStatistics = can.kvaser.CANLib.canGetBusStatistics(obj.Handle); % Return the property value according to the current chip % state. The value is scaled to be a percentage. out = busStatistics.BusLoad / 100; end function out = get.BusStatus(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Request the status from the driver. can.kvaser.CANLib.canRequestChipStatus(obj.Handle); % Read the status from the driver. chipStatus = can.kvaser.CANLib.canReadStatus(obj.Handle); % Return the property value according to the current chip state. if ~obj.Running out = 'N/A'; elseif chipStatus.ErrorActive out = 'ErrorActive'; elseif chipStatus.ErrorWarning out = 'ErrorWarning'; elseif chipStatus.ErrorPassive out = 'ErrorPassive'; elseif chipStatus.BusOff out = 'BusOff'; end end function out = get.ReceiveErrorCount(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Read the status from the driver. [~, out, ~] = can.kvaser.CANLib.canReadErrorCounters(obj.Handle); end function out = get.TransmitErrorCount(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Read the status from the driver. [out, ~, ~] = can.kvaser.CANLib.canReadErrorCounters(obj.Handle); end function out = get.SilentMode(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get the driver data. outputControlMode = can.kvaser.CANLib.canGetBusOutputControl(obj.Handle); % Return true or false for the property based on the channel % setting: canDRIVER_NORMAL 4, canDRIVER_SILENT 1. if outputControlMode == 1 out = true; else out = false; end end function set.SilentMode(obj, newValue) % Validate the channel before using its functionality. assertValidity(obj); % Verify that the channel is offline. if obj.Running error(message('vnt:Channel:ChannelNotOffline')); end % Check if the channel has initialization access. if ~obj.InitializationAccess error(message('vnt:Channel:NoInitAccessToChannel')); end % Validate the new value. validateattributes(newValue, {'logical'}, {'scalar'}, ... 'set.SilentMode', 'VALUE'); % Determine the value to pass to the driver based on the value % provided: canDRIVER_NORMAL 4, canDRIVER_SILENT 1. if newValue outputControlMode = 1; else outputControlMode = 4; end % Set the property. can.kvaser.CANLib.canSetBusOutputControl(obj.Handle, outputControlMode); end function out = get.TransceiverName(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get channel data for this device and channel. channelData = can.kvaser.Utility.getDriverData(... obj.DeviceCode,... obj.DeviceIndex,... obj.DeviceChannelIndex); % Return the property value. out = channelData.TransceiverName; end function out = get.TransceiverState(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get the driver data. [out, ~, ~] = can.kvaser.CANLib.canGetDriverMode(obj.Handle); end function set.TransceiverState(obj, newValue) % Validate the channel before using its functionality. assertValidity(obj); % Validate the input argument newValue. validateattributes(newValue, {'numeric'}, ... {'finite', 'integer', 'nonempty', 'nonnan', ... 'nonnegative', 'nonsparse', 'real', 'scalar'}, ... 'set.TransceiverState', 'VALUE'); % Set the property. can.kvaser.CANLib.canSetDriverMode(obj.Handle, newValue); % Check if the value of the property has been updated or been % reverted back to the last value by the driver. if newValue ~= obj.TransceiverState % Give a warning to the user. warning(message('vnt:Channel:ValueNotChanged')); end end function out = get.BusSpeed(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get and return the value for this property. [out, ~, ~, ~, ~] = can.kvaser.CANLib.canGetBusParams(obj.Handle); end function out = get.SJW(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get and return the value for this property. [~, ~, ~, out, ~] = can.kvaser.CANLib.canGetBusParams(obj.Handle); end function out = get.TSEG1(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get and return the value for this property. [~, out, ~, ~, ~] = can.kvaser.CANLib.canGetBusParams(obj.Handle); end function out = get.TSEG2(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get and return the value for this property. [~, ~, out, ~, ~] = can.kvaser.CANLib.canGetBusParams(obj.Handle); end function out = get.NumOfSamples(obj) % Validate the channel before using its functionality. if ~assertValidity(obj) % Return empty for any invalid object state. out = []; return; end % Get and return the value for this property. [~, ~, ~, ~, out] = can.kvaser.CANLib.canGetBusParams(obj.Handle); end function obj = saveobj(obj) % saveobj Saves the channel information to file. % % OBJ = saveobj(OBJ) saves the channel for future loading. The % channel information is saved as a structure to due to the % nature of the channel's underlying connection to third party % drivers and devices. % Set object properties into a structure for saving. Turn the % warning off to so that it does not show to the user. warnState = warning('OFF', 'MATLAB:structOnObject'); saveInfo = struct(obj); warning(warnState); % Remove fields that should not be saved. saveInfo = rmfield(saveInfo, 'AsyncioChannel'); saveInfo = rmfield(saveInfo, 'AsyncioReplayChannel'); saveInfo = rmfield(saveInfo, 'CustomEventListener'); saveInfo = rmfield(saveInfo, 'ReceiveCallbackListener'); % Set the output to save. obj = saveInfo; end end methods (Access = 'protected') function onAsyncioCustomEvent(obj, ~, ~) %#ok<MANU> % onAsyncioCustomEvent Callback function for event occurrence. % % onAsyncioCustomEvent(CANCH, SOURCE, DATA) is registered % with the Asyncio layer and is called upon custom event. end function filterSetInternal(obj, code, mask, idType) % filterSetInternal Sets hardware filters. % % This method is used internally by the hardware agnostic filtering % code to employ use of the hardware filters. There is a performance % benefit to block as many messages as possible via hardware filters % before applying software filtering on the channel. % Check the filter type to be set. switch idType case 'Standard' % Set the type code for use in the driver function call. idTypeCode = 0; case 'Extended' % Set the type code for use in the driver function call. idTypeCode = 1; end % Set the hardware filter. can.kvaser.CANLib.canSetAcceptanceFilter(obj.Handle, code, mask, idTypeCode); end function setInitialTimestamp(obj) % setInitialTimestamp Set the initial timestamp property value. % Convert the time value obtained from asyncio into a MATLAB % datetime object. obj.InitialTimestamp = can.Utility.calculateInitialTimestamp( ... obj.AsyncioChannel.InitialTimestamp); end end methods (Hidden) function delete(obj) % Stop the channel to ensure it offline when removed. The % channel is stopped in the asyncio layer directly. if ~isempty(obj.AsyncioReplayChannel) obj.AsyncioReplayChannel.close(); end if ~isempty(obj.AsyncioChannel) obj.AsyncioChannel.close(); end % Clean up any vendor driver links only if they were % initialized. This protects delete from generating errors on % partially failed construction. if ~isempty(obj.Handle) % Close the handle. can.kvaser.CANLib.canClose(obj.Handle); end end end methods (Static) function obj = loadobj(obj) % loadobj Load a channel from memory. % % OBJ = loadobj(OBJ) loads the channel from memory. The % information loaded comes as a structure from which a new % channel is built and configured to look like the previously % saved channel. % % Note that if an error happens while attempting to reconnect or % reconfigure the channel, an empty version of the channel is % returned. The empty object will not reach the user though. The % MATLAB object system will reconstruct an invalid version of the % channel with empty properties. Returning empty is done simply % to avoid a class type warning in the event of a load error. % Collect device information. info = canHWInfo(); % Determine if the vendor of the device for the channel % being loaded has devices currently installed on the system. vendorIndex = strmatch(... lower(obj.DeviceVendor),... lower({info.VendorInfo.VendorName}),... 'exact'); % Check for no match on the vendor. if isempty(vendorIndex) % Warn the user of the load issue. warning(message('vnt:Channel:CannotReconnectToDriver')); % Return an empty version of the channel. obj = can.kvaser.Channel.empty(); return; end % Create a list of device codes for matching the loaded % channel's device to what is currently available. deviceList = {info.VendorInfo(vendorIndex).ChannelInfo.Device}; for ii = 1:numel(deviceList) % Get the individual string pieces of the device string. deviceParts = textscan(deviceList{ii}, '%s'); deviceParts = cat(1, deviceParts{:})'; % Get the actual device name, which means remove the device % index off the end fo the device string. deviceKey = deviceParts{1}; for jj = 2:(numel(deviceParts) - 1) deviceKey = [deviceKey ' ' deviceParts{jj}]; %#ok<AGROW> end % Reference the device code for this device name. deviceCodes(ii) = can.kvaser.Utility.translateDeviceCode(deviceKey); %#ok<AGROW> end % Determine if the device is available to which the channel % being loaded was originally connected. This is done by % matching the serial number and channel index for the device % as well as the vendor device code. channelInfo = info.VendorInfo(vendorIndex).ChannelInfo(... obj.DeviceCode == deviceCodes &... obj.DeviceSerialNumber == [info.VendorInfo(vendorIndex).ChannelInfo.DeviceSerialNumber] &... obj.DeviceChannelIndex == [info.VendorInfo(vendorIndex).ChannelInfo.DeviceChannelIndex]); % Check for no match on the device. if isempty(channelInfo) % Warn the user of the load issue. warning(message('vnt:Channel:CannotReconnectToDevice')); % Return an empty version of the channel. obj = can.kvaser.Channel.empty(); return; end try % Recreate the loaded channel to rebuild a connection % to the device. newObj = canChannel(... info.VendorInfo(vendorIndex).VendorName,... channelInfo.Device,... channelInfo.DeviceChannelIndex); % Set the database in the channel only if the database file % was loaded properly for use. if ~isempty(obj.Database) && obj.Database.Usable newObj.Database = obj.Database; else newObj.Database = []; end % Some properties should only be restored if the newly % reconstructed channel has initialization access for the % device to which it is connected. if newObj.InitializationAccess % Reset the previous bus speed in advanced form to % replace the exact timings. configBusSpeed(newObj,... obj.BusSpeed,... obj.SJW,... obj.TSEG1,... obj.TSEG2,... obj.NumOfSamples); % Reset silent mode. newObj.SilentMode = obj.SilentMode; end % Restore the filters to their previous state by performing % each filter operation again. Note that due to changes made in % version 1.3 of this object, we no longer maintain forward or % backward compatibility to restore filter settings. Only % 1.3 and great versions will have state restored on load. if obj.Version >= 1.3 % Check the configured state and set the filters on the new % object accordingly for standard and extended filters. switch obj.FilterStateStandard.State case 'Allow All' newObj.filterAllowAll('Standard'); case 'Block All' newObj.filterBlockAll('Standard'); case 'Allow Only' newObj.filterAllowOnly(obj.FilterStateStandard.PassList, 'Standard'); end switch obj.FilterStateExtended.State case 'Allow All' newObj.filterAllowAll('Extended'); case 'Block All' newObj.filterBlockAll('Extended'); case 'Allow Only' newObj.filterAllowOnly(obj.FilterStateExtended.PassList, 'Extended'); end end % Reset other properties to match the saved state. newObj.MessageReceivedFcn = obj.MessageReceivedFcn; newObj.MessageReceivedFcnCount = obj.MessageReceivedFcnCount; newObj.TransceiverState = obj.TransceiverState; % Load the UserData. if obj.Version >= 1.4 newObj.UserData = obj.UserData; end % Load the InitialTimestamp. if obj.Version >= 1.5 newObj.InitialTimestamp = obj.InitialTimestamp; end % Set the new channel to return from loading. obj = newObj; catch err %#ok<NASGU> % Warn the user of the load issue. warning(message('vnt:Channel:CannotReconfigureChannel')); % Return an empty version of the channel. obj = can.kvaser.Channel.empty(); return; end end end end