Mesh sensor cadence

Hi everyone,

I am planning to use the cadence/publish interval property within a mesh network. I can not find any examples on how to use it. I know I can set it in the nrf mesh app but I would like to set the cadence in my implementation (like by clicking a button on the nrf52840DK). The sensor observer should be able to call the set function to set the cadence on a sensor server. Also the sensor observer should get some information about the cadence from the sensor server. Can anyone share some code on how to do it?

Best,

Toni

Parents
  • Okay I might already have the answer as the sensor observer can not set the cadence on the sensor server, can it?

  • Hi Toni,

    The Sensor Observer sample uses the Sensor Client model, which, by spec, has to support Sensor Cadence Set. See Section 4.4.1.1 of the Bluetooth Mesh Models Specification v1.0.1. I also captured the relevant table below.

    As for code reference, have you looked at these functions?

    bt_mesh_sensor_cli_cadence_set()
    bt_mesh_sensor_cli_cadence_set_unack()

    Best,

    Hieu

  • Hi Hieu,

    thank you the quick reply! I read it already and tried to implement it, but without success.
    I implemented the bt_mesh_sensor_present_ambient_light_level type and would like to get/set the candence settings on the server.
    First I want to get the cadence on the client by pressing a button on the DK. Therefore I use the function

    err = bt_mesh_sensor_cli_cadence_get(&sensor_cli, NULL, &bt_mesh_sensor_present_amb_light_level, &rsp);

    And on the sensor server I configured it like this:

    static struct bt_mesh_sensor present_amb_light_level = {
    	.type = &bt_mesh_sensor_present_amb_light_level,
    	.get = amb_light_level_get,
    	.descriptor = &amb_light_level_desc,
    	.settings = {
    		.list = (const struct bt_mesh_sensor_setting *)&amb_light_level_setting,
    		.count = ARRAY_SIZE(amb_light_level_setting),
    	},
    	.state = {
    		.configured = true,
    		.fast_pub = true,
    		.pub_div = 1,
    		.min_int = 10,
    		.threshold = {
    			.range = {
    				.cadence = BT_MESH_SENSOR_CADENCE_NORMAL,
    				.low = {
    					.format = &bt_mesh_sensor_format_count_16,
    					.raw = {0x00, 0x00} // Replace with the actual raw value for low
    				},
    				.high = {
    					.format = &bt_mesh_sensor_format_count_16,
    					.raw = {0x0A, 0x00} // Replace with the actual raw value for high
    				},
    			},
    			.deltas = {
    				.up = {
    					.format = &bt_mesh_sensor_format_count_16,
    					.raw = {0x02, 0x00} // Replace with the actual raw value for up
    				},
    				.down = {
    					.format = &bt_mesh_sensor_format_count_16,
    					.raw = {0x00, 0x00} // Replace with the actual raw value for down
    				},
    			},
    		},
    	},
    };

    I always get the error -ETIMEDOUT

    Could you provide some example code?

    Best,

    Toni

  • Hi Toni,

    I am currently out of office, so this will have to wait until I return next week. My apology about this.

    Best,

    Hieu

  • Hi Toni,

    My apology for the late reply and thank you for your patience.

    Regarding ETIMEDOUT, during my trials, I found that it can happen when I forgot to configure the Sensor Server Setup models to receive from the Sensor Client. Could you please check if that is the case for you?

    Beyond that, I am also getting it from the Sensor Client module being unable to process the response, with the warning:

    "type 0x%4x doesn't support cadence"

    This also ends up in ETIMEDOUT, but I think that is because the response could not be processed.
    I couldn't figure out why that is the case yet. I will need more time.

    Could you please check the Sensor Server Setup models have been configured correctly? I will also look into what is the issue with setting Cadence for the Ambient Light sensor.

    Best,

    Hieu

  • Hi Hieu,

    I can confirm that I always configure the Sensor Server Setup models to receive from the Sensor Client.

    Best,

    Toni

Reply Children
  • Hi Toni,

    Just letting you know that I am still looking into this. I tried giving the non-blocking method but met almost similar issues too.

    I will keep you updated.

    Best,

    Hieu

  • Hi Toni,

    Thank you for your patience. I got things to work in non-blocking mode today.

    Here is how I modified the Sensor Client's model_handler.c.

    static void sensor_cli_cadence_cb(struct bt_mesh_sensor_cli *cli,
                    struct bt_mesh_msg_ctx *ctx,
                    const struct bt_mesh_sensor_type *sensor,
                    const struct bt_mesh_sensor_cadence_status *cadence)
    {
        printk("Cadence for sensor with ID 0x%04x:\n", sensor->id);
        printk("\tFast cadence period: %d\n", cadence->fast_period_div);
        printk("\tMin int: %d\n", cadence->min_int);
    }
    
    
    static const struct bt_mesh_sensor_cli_handlers bt_mesh_sensor_cli_handlers = {
    	.data = sensor_cli_data_cb,
    	.series_entry = sensor_cli_series_entry_cb,
    	.setting_status = sensor_cli_setting_status_cb,
    	.sensor = sensor_cli_desc_cb,
    	.cadence = sensor_cli_cadence_cb,
    };
    
    
    static void button_handler_cb(uint32_t pressed, uint32_t changed)
    {
    	...
    	// Cadence SET --------------------
    	if (pressed & changed & BIT(0)) {
    		struct bt_mesh_sensor_value delta_up;
    		struct bt_mesh_sensor_value delta_down;
    		struct bt_mesh_sensor_value range_low;
    		struct bt_mesh_sensor_value range_high;
    
    		// NOTEs: Here, I directly used the sensor type, but you can also use bt_mesh_sensor_type_get to find the correct sensor type.
    		// I also used a value-based delta (using the same format as range), rather than percentage-based (where you'd need bt_mesh_sensor_format_percentage_delta_trigger)
    		bt_mesh_sensor_value_from_micro(bt_mesh_sensor_present_amb_light_level.channels[0].format,
    						1*1000000LL, &delta_up);
    		bt_mesh_sensor_value_from_micro(bt_mesh_sensor_present_amb_light_level.channels[0].format,
    						1*1000000LL, &delta_down);
    		bt_mesh_sensor_value_from_micro(bt_mesh_sensor_present_amb_light_level.channels[0].format,
    						1*1000000LL, &range_low);
    		bt_mesh_sensor_value_from_micro(bt_mesh_sensor_present_amb_light_level.channels[0].format,
    						1*1000000LL, &range_high);
    		struct bt_mesh_sensor_cadence_status cadence = {
    			.fast_period_div = 1,
    			.min_int = 1,
    			.threshold = {
    				.deltas = {
    					.up = delta_up,
    					.down = delta_down
    				},
    				.range = {
    					.cadence = BT_MESH_SENSOR_CADENCE_NORMAL,
    					.low = range_low,
    					.high = range_high
    				}
    			}
    		};
    
    		err = bt_mesh_sensor_cli_cadence_set(&sensor_cli, NULL,
    				&bt_mesh_sensor_present_amb_light_level,
    				&cadence,
    				NULL);
    	}
    
    	// Cadence GET --------------------
    	if (pressed & changed & BIT(1)) {
    		err = bt_mesh_sensor_cli_cadence_get(&sensor_cli, NULL, 
    							&bt_mesh_sensor_present_amb_light_level, 
    							NULL);
    							// &rsp);
    		printk("Non-blocking bt_mesh_sensor_cli_cadence_get err = %d\n", err);
    	}
    	...
    }

    A couple of pitfalls I found along the way are:

    • While configuring Cadence, only the Element that is being configured should subscribe to Sensor Client's messages.
      Otherwise, the other Elements will also receive the same message. This can cause some puzzling logs.
    • There can be some incorrect warning about invalid key and invalid address on the Server side if you don't configure the other Elements to also subscribe to Sensor Client's message. 
      This is a bug, but the system behavior is otherwise correct. They will be fixed. For now, please ignore them.

    Best,

    Hieu

Related