Listening for channel data with conditions

You must open the channel before starting to listen for channel data with conditions.

A condition is specified using the CSensrvChannelConditionSet class. A CSensrvChannelConditionSet contains one or more CSensrvChannelConditions.

When the condition is met, a notification is delivered via the data listener callback interface MSensrvChannelConditionListener::ConditionMet().

The following example shows how to start listening to double taps coming from the x-axis direction. The direction property from tapping data (TSensrvTappingData) is used as a condition in this example. The direction value is set to the x-axis plus and minus to get notification from double tap in both x-axis directions.

A condition set is created for a container for one or more conditions. A condition is created to hold a channel condition item, see detailed comments from the example below. The condition is added to the condition set and the condition set is added to the channel. The client has ownership of this condition set and it has to ensure that the condition set object is valid until the condition set is removed from the channel or the channel is destroyed.

After the condition set is added to the channel, the condition listening is started with the StartConditionListeningL() method.

The client needs to provide a pointer to the condition listener for the channel to be able to receive the ConditionMet() notification.

    CSensrvChannelCondition* condition = NULL;

    // Condition for double tapping channel is set so that
    // double tap to X-axis triggers condition met notification
    TSensrvTappingData doubleTappingCondition;
    TPckgC<TSensrvTappingData> doubleTappingConditionPckg( doubleTappingCondition );
    doubleTappingCondition.iTimeStamp = 0;    
    doubleTappingCondition.iDirection = KSensrvAccelerometerDirectionXplus | KSensrvAccelerometerDirectionXminus;

    // In this example logical operator to be used in the condition set
    // does not have any effect because only one condition is added
    // to the condition set
    iConditionSet = CSensrvChannelConditionSet::NewL( ESensrvOrConditionSet );
    
    // Binary condition (ESensrvBinaryCondition) is used because double tapping 
    // channel provides bitmask values.
    // Binary and (ESensrvOperatorBinaryAnd) operator is used because operator 
    // checks if a bitmask data value got from double tapping channel has set at least
    // one of the bits set in the condition value. 
    // In other words double tapping direction can be positive or negative. 
    // Item index (3rd parameter) defines which attribute in data item is used for condition evaluation.
    // TSensrvTappingData::Index::iDirection means that iDirection is used 
    // for condition from TSensrvTappingData class.
    // Last parameter (doubleTappingConditionPckg) contains value for 
    // condition evaluation encapsulated in the package descriptor.
    condition = CSensrvChannelCondition::NewLC( ESensrvBinaryCondition,
                                                ESensrvOperatorBinaryAnd,
                                                TSensrvTappingData::Index::iDirection,
                                                doubleTappingConditionPckg );

    //Add condition to condition set
    iConditionSet->AddChannelConditionL( condition );
    
    //Don't delete condition since ownership is transferred to condition set
    CleanupStack::Pop( condition ); 

    // Add condition set for the double tapping channel
    iDoubleTappingConditionChannel->AddConditionL( *iConditionSet );

    // Start condition listening
    //  aObjectCount is one, i.e. each double tapping condition is notified separately
    //  buffering period is not used, i.e. it is set to zero
    iDoubleTappingConditionChannel->StartConditionListeningL( iDataListener2,
                                                              1,
                                                              0 );

To implement condition listener, the client needs to inherit from the MSensrvChannelConditionListener interface class and implement the declared pure virtual methods.

When a channel condition set is met and condition listening is started, the ConditionMet() method is called by sensor framework.

The following example shows how to handle condition met notification for double tapping channel.

First the channel type of the received data and correct data buffer size is checked. The received data object is encapsulated in package descriptor thus channel data value which met the condition is copied to a new package buffer. If the client wants to use the same condition set after notification, the client has to add the condition set again to the channel object.

    void CTestClass::ConditionMet( CSensrvChannel& aChannel,
                               CSensrvChannelConditionSet& aChannelConditionSet,
                               TDesC8& aValue )
    {

    if( aChannel.GetChannelInfo().iChannelType == KSensrvChannelTypeIdAccelerometerDoubleTappingData )
        {
        if ( sizeof(TSensrvTappingData) == aValue.Size() )
            {
            TPckgBuf<TSensrvTappingData> dataBuf;
            dataBuf.Copy( aValue ); 

            //dataBuf() contains channel data value which met the condition

            //Use the same condition set again
            if( iDoubleTappingConditionChannel )
                {
                // Add condition set for the double tapping channel.
                // Condition listening is not stopped thus
                // only new condition set is needed to be added.
                iDoubleTappingConditionChannel->AddConditionL( *iConditionSet );
                }
            }
        else
            {
            //Size of the aValue was unexpected
            }
        }
    else
        {
        //Condition was not met for double tapping channel
        }
	    
    }