Docs

You are here:
Message filters

Using message filters

In addition to polling the connection for incoming messages using RCM_GetPendingMessage function (see rcm_exchange), the RCM library provides alternative mechanism for receiving messages. It is called Message filtering.

The idea is that the user provides and installs in the connection a filter that includes a filtering function. This function is run against every received message. The filtering function can capture the message data and decide whether the message is already processed (it then returns true) or not (returns false).

The filters are installed in a chain. A received message passes this chain until one of the filters catches it. In case no filter catches the message, it is being stored in the message buffer and will be available through the RCM_GetPendingMessage function.

A filter can be installed in the connection using RCM_InsertMessageFilterInBack or RCM_InsertMessageFilterInFront and removed using RCM_RemoveMessageFilter.

An example of RCM module configuration

The following example illustrates the usage of message filtering:

#include "rcm.h"
// Structure holding information about the connection
static RCMConnection rcm;
// Declare a structure named frameBuffer, that will fit infinite SCOM packets
static SCOM_DECLARE_FRAME_BUFFER_USING_HEAP(frameBufferInHeap);
// Declare a structure named messageBufferInHeap that can fit unlimited number of RCM messages
static RCM_DECLARE_MESSAGE_BUFFER_USING_HEAP(messageBufferInHeap);
// Function that will be used as a first message filter
bool rcmFilterProc1(RCMConnection* rcm, struct RCMMessageFilter *filter, RCMMessage* message)
{
// For the demonstration purpose, this function checks if the received message came from a node
// with short address of one. If if did, the message is sent back to this node
// check addressing mode and address
if ((message->srcAddrMode == RCM_ADDR_MODE_SHORT_ADDRESS) && (message->srcAddr.shortAddr == 1)) {
// got message from node with short address 1
// WARNING: You cannot use RCM API calls within the filter proc. During filter processing the
// RCM connection object is locked and should not be altered. Instead acquire information
// about the received message and pass it to the main control loop of your program.
// returning true indicates that the message was filtered out and should be deleted
return true;
}
// returning false indicates that this filter did not "catch" the message
return false;
}
// Function that will be used as a second message filter
bool rcmFilterProc2(RCMConnection* rcm, struct RCMMessageFilter *filter, RCMMessage* message)
{
// filter out all messages, so that they don't end up in the received message buffer
return true;
}
int rcm_message_filtering_example(IODevice iodevice)
{
int result = 0;
RCMMessage* receivedMessage;
RCMMessageFilter filter1, filter2;
OSTime startTime;
// get current time
startTime = OS_GetSystemTime();
// try to open the connection using specified IODevice
if (RCM_RESULT_OK == RCM_Open(&rcm, iodevice, &frameBufferInHeap, &messageBufferInHeap, OS_GetSystemTime)) {
// connection opened, run it
if (RCM_RESULT_OK == RCM_Run(&rcm)) {
// threads run successfully
// configure the RCM module
RCM_SetUID(&rcm, 0x0123456789abcdef);
// Register an endpoint: EP1
// Initialize generic message filters
RCM_InitMessageFilter(&filter1, rcmFilterProc1, NULL);
RCM_InitMessageFilter(&filter2, rcmFilterProc2, NULL);
// Insert the message at the end of the filtering chain
if (RCM_RESULT_OK == RCM_StartNetworking(&rcm)) {
// network established successfully
// now all messages will be filtered by the filters
// in the loop, check only the state of connection
while (0 == result) {
// 1s delay
OS_Sleep(1000);
// check connection
while (RCM_RESULT_OK != RCM_GetConnectionState(&rcm)) {
// connection broke down (hardware error?)
// exit with error code
result = 2;
}
// check timeout
if (OS_GetSystemTime() - startTime > 10000) {
// timeout
break;
}
}
}
// stop the RCM threads
RCM_Stop(&rcm);
} else {
// error
result = 2;
}
// finally close the connection
RCM_Close(&rcm);
} else {
// error
result = 1;
}
return result;
}

messages by endpoint

Often, the filter will be designed in such a way, that will filter out messages comming through a given endpoint. Fot that purposes a special kind of filter is already provided by the RCM library.

The Endpoint message filter filters messages received through a given endpoint and stores them in it's own message buffer. In order to use the endpoint message filter, the user must first initialize it using RCM_InitEndpointMessageFilter and then install it in the connection using RCM_InsertMessageFilterInBack or RCM_InsertMessageFilterInFront. Once the filter is in place, the user can call RCM_GetMessageFromEndpointMessageFilter to check if new messages were received. This function has also the ability to block the calling thread until message arrives or timeout is reached. The received messages need to be deleted by the user, by calling RCM_UnlockEndpointMessage. An unused endpoint message filter should be deinitialized using RCM_DeinitEndpointMessageFilter.

Example of endpoint filtering

The following example illustrates the usage of endpoint message filter:

#include "rcm.h"
// Structure holding information about the connection
static RCMConnection rcm;
// Declare a structure named frameBuffer, that will fit infinite SCOM packets
static SCOM_DECLARE_FRAME_BUFFER_USING_HEAP(frameBufferInHeap);
// Declare a structure named messageBufferInHeap that can fit unlimited number of RCM messages
static RCM_DECLARE_MESSAGE_BUFFER_USING_HEAP(messageBufferInHeap);
// Declare a structure named epMessageBufferInHeap that can fit unlimited number of RCM messages - for endpoint filtering
static RCM_DECLARE_MESSAGE_BUFFER_USING_HEAP(epMessageBufferInHeap);
int rcm_endpoint_filtering_example(IODevice iodevice)
{
int result = 0;
RCMMessage* receivedMessage;
OSTime startTime;
// get current time
startTime = OS_GetSystemTime();
// try to open the connection using specified IODevice
if (RCM_RESULT_OK == RCM_Open(&rcm, iodevice, &frameBufferInHeap, &messageBufferInHeap, OS_GetSystemTime)) {
// connection opened, run it
if (RCM_RESULT_OK == RCM_Run(&rcm)) {
// threads run successfully
// configure the RCM module
RCM_SetUID(&rcm, 0x0123456789abcdef);
// Register an endpoint: EP1
// Initialize endpoint message filters
RCM_InitEndpointMessageFilter(&filter, 1, &epMessageBufferInHeap);
// Insert the message at the end of the filtering chain
if (RCM_RESULT_OK == RCM_StartNetworking(&rcm)) {
// network established successfully
// since only one endpoint is registered, all messages will be filtered by the endpoint filter
// in the loop, check only the state of connection
while (0 == result) {
// 1s delay
OS_Sleep(1000);
// check connection
while (RCM_RESULT_OK != RCM_GetConnectionState(&rcm)) {
// connection broke down (hardware error?)
// exit with error code
result = 2;
}
// check timeout
if (OS_GetSystemTime() - startTime > 5000) {
// timeout
break;
}
}
}
// stop the RCM threads
RCM_Stop(&rcm);
} else {
// error
result = 2;
}
// finally close the connection
RCM_Close(&rcm);
} else {
// error
result = 1;
}
return result;
}
Go to Top