Using Events and Timers with the Silicon Labs Matter Extension#

Event Handler#

The Matter event handler uses the FreeRTOS queue to transport a message from the producer to the consumer area. Events can be used to create an asynchronous message processing or an inter-task message communication.

Steps to make an event work:

  • Make sure the queue is initialized

  • Create an AppEventType for your application

  • Populate the Type and Handler variables

  • Post the message to the queue

Event definition enum#

AppEvent contains event types and event structures that are used for specific applications, if needed. Handler is used to store the callback for the event.

struct AppEvent
{
    enum AppEventTypes
    {
        kEventType_Button = 0,
        kEventType_Timer,
        kEventType_Light,
        kEventType_Install,
        kEventType_Observer,
    };

    uint16_t Type;

    union
    {
        struct
        {
            uint8_t Action;
        } ButtonEvent;
        struct
        {
            void * Context;
        } TimerEvent;
        struct
        {
            uint8_t Action;
            int32_t Actor;
        } LightEvent;
    };

    EventHandler Handler;
};

Queue Posting#

When creating an event and pushing it to the event queue at minimum, Handler and Type must be defined in order for the event to work.

void AppTask::CreateObserverEvent(void)
{
    AppEvent active_mode_event = {};
    active_mode_event.Type     = AppEvent::kEventType_Observer;
    active_mode_event.Handler  = SilabsSensors::SendSensorsValues;

    sAppTask.PostEvent(&active_mode_event);
}

Callback#

Observer event callback

void SilabsSensors::SendSensorsValues(AppEvent * aEvent)
{
    // Do something
}

Dispatcher#

AppTaskMain is dispatching all the events from the event list.

void AppTask::AppTaskMain(void * pvParameter)
{
    AppEvent event;
    QueueHandle_t sAppEventQueue = *(static_cast<QueueHandle_t *>(pvParameter));

    CHIP_ERROR err = sAppTask.Init();
    if (err != CHIP_NO_ERROR)
    {
        SILABS_LOG("AppTask.Init() failed");
        appError(err);
    }

#if !(defined(CHIP_CONFIG_ENABLE_ICD_SERVER) && CHIP_CONFIG_ENABLE_ICD_SERVER)
    sAppTask.StartStatusLEDTimer();
#endif

    sAppTask.RegisterObserver();

    SILABS_LOG("App Task started");

    while (true)
    {
        BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, portMAX_DELAY);
        while (eventReceived == pdTRUE)
        {
            sAppTask.DispatchEvent(&event);
            eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
        }
    }
}

Matter Timer#

Start#

Initialize a one-shot timer to expire in 10 seconds and invoke TestCallback upon expiration.

System::Clock::Timeout Timeout = System::Clock::Seconds32(10);

chip::DeviceLayer::PlatformMgr().LockChipStack();
err = DeviceLayer::SystemLayer().StartTimer(Timeout, TestCallback, this);
chip::DeviceLayer::PlatformMgr().UnlockChipStack();

Callback#

Timer callback.

void AppTask::TestCallback(System::Layer * layer, void * aAppState)
{
	// Do something
}

If you need a periodic timer, you can recall StartTimer() in the callback.