%% Use Message Filters in CAN Communication
% This example shows you how to use CAN message filters to allow only messages that contain specified identifiers to pass through a channel. It uses MathWorks virtual CAN channels connected in a loopback configuration. This example describes the workflow for a CAN network, but the concept demonstrated also applies to a CAN FD network.
%
%% Create Transmitting and Receiving Channels
% Create one channel for transmitting messages and another channel for receiving. Filters are set later on the receiving channel.

txCh = canChannel("MathWorks", "Virtual 1", 1)
rxCh = canChannel("MathWorks", "Virtual 1", 2)

%
%% Create Messages
% Create a few messages to be sent to the receiving channel multiple times throughout the example. Note that one message has an extended identifier.

txMsgs(1) = canMessage(250, false, 8);
txMsgs(2) = canMessage(500, false, 8);
txMsgs(3) = canMessage(1000, false, 8);
txMsgs(4) = canMessage(1500, true, 8);
txMsgs(5) = canMessage(2000, false, 8);

%
%% Receive Messages with No Filter
% Set the channels online, transmit the messages on one channel, and receive on the other. Note that all messages sent are received. By default, a newly created channel with no filter configured receives all standard and extended identifiers.

start(rxCh);
start(txCh);
transmit(txCh, txMsgs);
pause(0.5);
rxMsgs1 = receive(rxCh, Inf, "OutputFormat", "timetable")

% Stop both receiving and transmitting channels.

stop(rxCh);
stop(txCh);

% Plot identifiers of the received messages to see that all messages sent are received by the channel.

plot(1, rxMsgs1.ID, "x")
h_gca = gca;
h_gca.XTick = 0:1:2;
h_gca.XTickLabel = ["", "Transmit 1", ""];
axis([0 2 0 2047])
xlabel("Message Transmits")
ylabel("CAN Identifiers")

%
%% Receive Messages with Filters Configured by Identifier
% Use the filterAllowOnly command to allow only specified messages by CAN identifier and identifier type. Configure the receiving channel to only receive messages with standard identifiers 500 and 2000.

filterAllowOnly(rxCh, [500 2000], "Standard");

% Display the FilterHistory property of the channel to view the configured state of the message filters.

rxCh.FilterHistory

% Transmit the messages again to the receiving channel. Note that fewer messages are received this time.

start(rxCh);
start(txCh);
transmit(txCh, txMsgs);
pause(0.5);
rxMsgs2 = receive(rxCh, Inf, "OutputFormat", "timetable")

% Stop both receiving and transmitting channels.

stop(rxCh);
stop(txCh);

% Add the newly received data to the plot to see which messages passed the filters. The message with extended identifier 1500 is not blocked by the filter because the filter was only configured for standard identifiers.

plot(1, rxMsgs1.ID, "x", 2, rxMsgs2.ID, "x");
h_gca = gca;
h_gca.XTick = 0:1:3;
h_gca.XTickLabel = ["", "Transmit 1", "Transmit 2", ""];
axis([0 3 0 2047])
xlabel("Message Transmits")
ylabel("CAN Identifiers")

%
%% Reset the Message Filters
% Reset the message filters to the default states with the  filterAllowAll command so that all standard identifiers are allowed.

filterAllowAll(rxCh, "Standard");

% Display the FilterHistory property of the channel to view the configured state of the message filters.

rxCh.FilterHistory

% Transmit and receive for a third time to see that all messages are once again passing through the filters and received by the receiving channel.

start(rxCh);
start(txCh);
transmit(txCh, txMsgs);
pause(0.5);
rxMsgs3 = receive(rxCh, Inf, "OutputFormat", "timetable")

% Stop both receiving and transmitting channels.

stop(rxCh);
stop(txCh);

% With the new data added to the plot, observe that the first and third transmits are identical as the message filters are fully open in both cases.

plot(1, rxMsgs1.ID, "x", 2, rxMsgs2.ID, "x", 3, rxMsgs3.ID, "x")
h_gca = gca;
h_gca.XTick = 0:1:4;
h_gca.XTickLabel = ["", "Transmit 1", "Transmit 2", "Transmit 3", ""];
axis([0 4 0 2047])
xlabel("Message Transmits")
ylabel("CAN Identifiers")

%
%% Receive Messages with Filters Configured by Name
% The filterAllowOnly command can also filter messages by name when using a DBC-file. Allow only messages with name EngineMsg.

db = canDatabase("demoVNT_CANdbFiles.dbc");
rxCh.Database = db;
filterAllowOnly(rxCh, "EngineMsg");
rxCh.FilterHistory

%
%% Block All Messages of a Specific Identifier Type
% The filterBlockAll command allows you to easily set the filters to block all messages of either standard or extended identifier type. Block all messages with extended identifiers.

filterBlockAll(rxCh, "Extended");
rxCh.FilterHistory

%
%% Stop the Channels
% Stop both receiving and transmitting channels and clear them from the workspace.

stop(rxCh);
stop(txCh);
clear rxCh txCh

%
%% Close the DBC-File
% Close access to the DBC-file by clearing its variable from the workspace.

clear db

%
% Copyright 2009-2021 The MathWorks, Inc.