Scenes Cluster Client on Matter Remote Controller

Dear Support Team,
 
    I'm developing a Matter remote controller and want to implement Scenes Cluster Client functionality. When a button is pressed, the remote should recall a specific scene (e.g., Scene ID 5) on target devices.

I have three questions:

1. How to provision the Scene ID to the remote? Should the Scene ID be stored in the Binding Table, or is there a dedicated attribute for this?

2. How to recall the scene on button press? Should the remote send a groupcast RecallScene command, or is there another standard way?

3. What are the exact chip-tool commands to configure this? I need a step-by-step example (bind remote button to group + assign Scene ID).

Background: NCS 3.1.1 / nRF54L15. On/Off binding already works.

Thanks for your help!

Parents
  • Hello,

    1. How to provision the Scene ID to the remote? Should the Scene ID be stored in the Binding Table, or is there a dedicated attribute for this?

    In the Matter spec there is only descriptions about how to store the scene ID on the server, so for the client case, this is up to the application. Ultimately you can decide how you want to do this, but here are some options:

    Hardcoding it and mapping buttons directly to the scene, but keep in mind that it will be fixed during development, e.g.:

    constexpr chip::SceneId kButton1Scene = 0x01;
    constexpr chip::SceneId kButton2Scene = 0x05;

    Looking into if you can use KeyValueStorMgr. This requires it to be configurable at runtime with your application:

    // Write during provisioning
    chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr()
        .Put("scene/btn1", &sceneId, sizeof(sceneId));
    
    // Read on button press
    chip::SceneId sceneId;
    chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr()
        .Get("scene/btn1", &sceneId, sizeof(sceneId));

    2. How to recall the scene on button press? Should the remote send a groupcast RecallScene command, or is there another standard way?

    Your intuision is correct: groupcasting RecallScene will be the best way. Our light switch sample uses this method. 

    So this should be added in the equivalent of LightSwitch::SwitchChangedHandler():

    if (binding.type == Binding::MATTER_MULTICAST_BINDING &&
        bindingData.ClusterId == chip::app::Clusters::ScenesManagement::Id)
    {
        chip::app::Clusters::ScenesManagement::Commands::RecallScene::Type cmd;
        cmd.groupID   = binding.groupId;
        cmd.sceneID   = bindingData.Value;
    
        chip::Messaging::ExchangeManager &exchangeMgr =
            chip::Server::GetInstance().GetExchangeManager();
    
        chip::Controller::InvokeGroupCommandRequest(
            &exchangeMgr, binding.fabricIndex, binding.groupId, cmd);
    }

    And on a button press it can be triggered with something like this:

    void OnButton1Pressed()
    {
        auto *data = chip::Platform::New<Nrf::Matter::BindingHandler::BindingData>();
        data->EndpointId        = mSwitchEndpoint;
        data->ClusterId         = chip::app::Clusters::ScenesManagement::Id;
        data->CommandId         = chip::app::Clusters::ScenesManagement::Commands::RecallScene::Id;
        data->Value             = 0x05;  // Scene ID 5 just as an example
        data->IsGroup           = chip::MakeOptional(true); // force groupcast
        data->InvokeCommandFunc = SceneRecallHandler;
        Nrf::Matter::BindingHandler::RunBoundClusterAction(data);
    }

    3. What are the exact chip-tool commands to configure this? I need a step-by-step example (bind remote button to group + assign Scene ID).

    Commissiong both devices (remote and target device) with chip-tool pairing.

    Create a group and add the target device to it:

    chip-tool groups add-group <group-id> "<group-name>" <target-node-id> <target-endpoint-id>

    Add the scene to the target device using either AddScene or StoreScene, for example:

    chip-tool scenesmanagement add-scene <group-id> <scene-id> <transition-time> "<scene-name>" [] <target-node-id> <target-endpoint-id>

    Add the remote to the group (for keyset/groupcast ACL)

    chip-tool groups add-group <group-id> "<group-name>" <remote-node-id> <remote-endpoint-id>

    Write a binding on the remote:

    chip-tool binding write binding '[{"fabricIndex": <fabric-id>, "group": <group-id>}]' <remote-node-id> <remote-endpoint-id>

    Verify that the scene exists on the target device. This should list scene ID with the ID provided earlier.

    chip-tool scenesmanagement get-scene-membership <group-id> <target-node-id> <target-endpoint-id>

    Then test that RecallScene works by pressing the button on the remote. It is also possible to test with chip-tool:

    chip-tool scenesmanagement recall-scene <group-id> <scene-id> <target-node-id> <target-endpoint-id>

    Best regards,

    Maria

Reply
  • Hello,

    1. How to provision the Scene ID to the remote? Should the Scene ID be stored in the Binding Table, or is there a dedicated attribute for this?

    In the Matter spec there is only descriptions about how to store the scene ID on the server, so for the client case, this is up to the application. Ultimately you can decide how you want to do this, but here are some options:

    Hardcoding it and mapping buttons directly to the scene, but keep in mind that it will be fixed during development, e.g.:

    constexpr chip::SceneId kButton1Scene = 0x01;
    constexpr chip::SceneId kButton2Scene = 0x05;

    Looking into if you can use KeyValueStorMgr. This requires it to be configurable at runtime with your application:

    // Write during provisioning
    chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr()
        .Put("scene/btn1", &sceneId, sizeof(sceneId));
    
    // Read on button press
    chip::SceneId sceneId;
    chip::DeviceLayer::PersistedStorage::KeyValueStoreMgr()
        .Get("scene/btn1", &sceneId, sizeof(sceneId));

    2. How to recall the scene on button press? Should the remote send a groupcast RecallScene command, or is there another standard way?

    Your intuision is correct: groupcasting RecallScene will be the best way. Our light switch sample uses this method. 

    So this should be added in the equivalent of LightSwitch::SwitchChangedHandler():

    if (binding.type == Binding::MATTER_MULTICAST_BINDING &&
        bindingData.ClusterId == chip::app::Clusters::ScenesManagement::Id)
    {
        chip::app::Clusters::ScenesManagement::Commands::RecallScene::Type cmd;
        cmd.groupID   = binding.groupId;
        cmd.sceneID   = bindingData.Value;
    
        chip::Messaging::ExchangeManager &exchangeMgr =
            chip::Server::GetInstance().GetExchangeManager();
    
        chip::Controller::InvokeGroupCommandRequest(
            &exchangeMgr, binding.fabricIndex, binding.groupId, cmd);
    }

    And on a button press it can be triggered with something like this:

    void OnButton1Pressed()
    {
        auto *data = chip::Platform::New<Nrf::Matter::BindingHandler::BindingData>();
        data->EndpointId        = mSwitchEndpoint;
        data->ClusterId         = chip::app::Clusters::ScenesManagement::Id;
        data->CommandId         = chip::app::Clusters::ScenesManagement::Commands::RecallScene::Id;
        data->Value             = 0x05;  // Scene ID 5 just as an example
        data->IsGroup           = chip::MakeOptional(true); // force groupcast
        data->InvokeCommandFunc = SceneRecallHandler;
        Nrf::Matter::BindingHandler::RunBoundClusterAction(data);
    }

    3. What are the exact chip-tool commands to configure this? I need a step-by-step example (bind remote button to group + assign Scene ID).

    Commissiong both devices (remote and target device) with chip-tool pairing.

    Create a group and add the target device to it:

    chip-tool groups add-group <group-id> "<group-name>" <target-node-id> <target-endpoint-id>

    Add the scene to the target device using either AddScene or StoreScene, for example:

    chip-tool scenesmanagement add-scene <group-id> <scene-id> <transition-time> "<scene-name>" [] <target-node-id> <target-endpoint-id>

    Add the remote to the group (for keyset/groupcast ACL)

    chip-tool groups add-group <group-id> "<group-name>" <remote-node-id> <remote-endpoint-id>

    Write a binding on the remote:

    chip-tool binding write binding '[{"fabricIndex": <fabric-id>, "group": <group-id>}]' <remote-node-id> <remote-endpoint-id>

    Verify that the scene exists on the target device. This should list scene ID with the ID provided earlier.

    chip-tool scenesmanagement get-scene-membership <group-id> <target-node-id> <target-endpoint-id>

    Then test that RecallScene works by pressing the button on the remote. It is also possible to test with chip-tool:

    chip-tool scenesmanagement recall-scene <group-id> <scene-id> <target-node-id> <target-endpoint-id>

    Best regards,

    Maria

Children
No Data
Related