Issues related to Matter over Thread product interfaces for reporting brightness changes to the APP

We are developing a light product that features a built-in button. A single click of this button toggles the light on/off, while a long press adjusts the brightness level.

If we manually adjust the brightness and then report the new brightness level via the Clusters::LevelControl::Attributes::CurrentLevel::Set() interface, this action triggers the MatterPostAttributeChangeCallback() command to set the brightness (which involves receiving commands for the transition from the current value to the target value).

Since our intent is solely to report the new brightness to the app without triggering a control command, this creates a conflict.

Is there an interface that allows us to only report the brightness state without subsequently receiving a dimming/setting command?

Parents
  • Hi,

    The MatterPostAttributeChangeCallback() function is always called when an attribute value is changed, and since the Set() function changes the CurrentLevel attribute, MatterPostAttributeChangeCallback() will be called.

    Can you clarify what you mean by MatterPostAttributeChangeCallback() triggering a control command? How have you implemented this function?

    Best regards,
    Marte

  • After the device-side button triggers a brightness change, I need to notify the mobile app of the updated brightness state. Which API should I use?

    If I use the set() function to report the brightness state, I receive an unwanted brightness change callback (MatterPostAttributeChangeCallback()) during the reporting process.

    Is there an API that can directly report brightness without triggering this callback?

  • Hi,

    You need to update the attribute value locally on the device, and Set() is the correct way to do this. Can you explain why MatterPostAttributeChangeCallback() being called is causing a problem in your application? 

    Best regards,
    Marte

  • When the internal dimming ramp time is set to 10 seconds, I need to notify the mobile app that the target brightness has reached 254. However, after the device reports this brightness update, it receives a series of brightness callbacks (transitioning from 0 to 254) during the fade process. These intermediate values then unexpectedly modify the device's target brightness again, creating an undesirable control loop.

  • Hi,

    If you need to update the mobile app only when the brightness has reached 254 and not any values during the transition, the best option is to call Set() only once to update the attribute value once the transition is complete. 

    MatterPostAttributeChangeCallback() is automatically called by the Matter Data Model engine directly after an attribute value is changed, regardless of whether the change occurred due to a local action or as a result of receiving a command from a remote device. This is the intended behavior of the callback, and it is meant to synchronize the attribute value between the Data Model and the application state.

    You can read more about this in Matter APIs.

    Best regards,
    Marte

  • Do you know the differences between these API interfaces? Is there any interface that can meet my needs?

Reply Children
  • Hi,

    The functions differ in what value they set and whether they mark the attribute as "dirty", i.e. needing to be reported/updated.

    Set(EndpointId endpoint, uint8_t value);

    This sets the attribute to a specific non-null uint8_t value.

    Set(EndpointId endpoint, uint8_t value, MarkAttributeDirty markDirty);

    This is the same as above, but allows you to specify whether to mark the attribute as dirty. "Dirty" in this context means the attribute has changed and the system should notify/report this change. 

    The default is MarkAttributeDirty::kIfChanged, which means that the system is only notified if the attribute value is changed. This is the behavior when using Set() without dirty. When using the variant of the function that includes markDirty, you can suppress or force reporting even if the value changed or did not change, by setting markDirty to kNo or kYes.

    SetNull(EndpointId endpoint);

    Sets the attribute to a "null" value.

    SetNull(EndpointId endpoint, MarkAttributeDirty markDirty);

    Same as SetNull(), but you can mark the attribute as dirty.

    Set(EndpointId endpoint, const chip::app::DataModel::Nullable<uint8_t> & value);

    Sets the attribute to either a specific value or null depending on the Nullable wrapper. So, while the first Set() function handles the case where the attribute is a specific value and SetNull() handles when it is null, this function can handle both those cases. It is a more generic function and is useful in situations where you might want to handle both cases with a single call, especially if the value comes from a source that may or may not be null (e.g. user input).

    Set(EndpointId endpoint, const chip::app::DataModel::Nullable<uint8_t> & value, MarkAttributeDirty markDirty);

    Same above, but you can mark the attribute as dirty.

    Best regards,
    Marte

Related