BT MESH: Setting values for models internally

Hello,

for a device I'm developing I need to be able to set values from an App as well as from the device itself (buttons on said device). So far everything works fine, from the outside the set and get handlers are called, from the "inside" publishing methods are called. This results in a consistent state between device and app.

However there is one case that breaks in the light_lightness_server_model:

  • Set lightness of 100 (or any value X) using the app
  • press button that sets lightness to 250 (or any value Y!=X) on the device

At this point app and device show a value of 250, which is correct.

  • now turn the lightness server off via the application (this sets a brightness of 0)

Now both ends show 0 or off.

But now comes the broken part:

  • Turn the lightness server back on using the application

The expected value would be a 250 as it was the last value that was published by the device. The actual value entering the set handler however is 100.

Why is that? Because the model handles its state internally and publishing a new state does not change whatever is held within the model.

I have looked for functions to set these values from the firmware but so far haven't found anything that works. I tried using a client within the same firmware, but that requires me to set an application key for said client as well. I tried using functions from the opcode handler list, but these require handcrafting buffers and somehow tracking transaction ids.

So my question is: Is there a simple way of just setting a value given some model?

Parents Reply Children
  • Which example from the SDK are you basing your project on?

  • It's based on the USB console example as I'm working with the dongle.

    As said above, everything works fine with mesh except for setting values on the chip directly. I don't know how to set them or if that is even possible.

    So the problem is, if I set something with the mobile app, then the corresponding set_handler such as:

    static void brightness_set_handler(struct bt_mesh_lightness_srv *srv,
    		      struct bt_mesh_msg_ctx *ctx,
    		      const struct bt_mesh_lightness_set *set,
    		      struct bt_mesh_lightness_status *rsp);

    Is called and the state is properly set. Then I when I press a button on the node itself I want to set a dfiferent value and publish it like this:

    int tn_mesh_publish_lightness(struct bt_mesh_lightness_srv server, uint16_t value) {
        struct bt_mesh_lightness_status status = {
            .current = value
        };
    
        return bt_mesh_lightness_srv_pub(&server, &context, &status);
    }

    This results in both, the node and the mobile app to show what ever was set via the button.

    But now when I turn the model off and on again via the mobile app, the off setz a 0 while keeping the old state that was set via the - mobile app - not what was published via bt_mesh_lightness_srv_pub.

    I think that's the case because pub just publishes the value but doesn't override the internal state of the model.

    That is why I'm asking whether I'm supposed to have a client on the same node for such a functionality or if there is another way of actually setting the internal state.

  • Hi,

    If no API is exposed the way to do this is by instantiating a client on the same node, yes. However, the incorrect last value showing up after light off -> light on seems suspicious.

    EDIT: Like you say. You just publish the value, making it show up in the app. The actual last state is stored in the server model and not changed by doing this, and this is what is used when turning off and then on again. If you want local control of a lightness server, the supported way to do this is indeed a lightness client on the same node. This goes for (nearly) all of the models, they only expose control through the mesh messages.

Related