Code Walkthrough#

As of BT Mesh SDK v6.x, the code structure of both the stack API and the code examples have been reworked. The Bluetooth Mesh API now abstracts away much of the event handling in generated files and allows the user to focus on application development. Much functionality is now hidden in the components, making the user application simpler.

The sections below describe the code in the application source of the examples (app.c and components).

Unprovisioned Mode, Provisioning, and Configuration#

In unprovisioned mode, both examples behave the same way. The unprovisioned device simply starts sending unprovisioned beacons and waits for a provisioner to provision and configure it.

When the app_init is being called, the application checks if a button is pressed in the handle_reset_conditions function. If yes, depending on the pressed button(s), it calls either the function sl_btmesh_initiate_full_reset(), which halts the system and performs a factory reset by erasing the NVM3 storage, or the function sl_btmesh_initiate_node_reset(), which does the same, except performs full NVM storage erasure. The factory reset is also done after receiving a node_reset event (sl_btmesh_evt_node_reset_id). This is handled within the Factory Reset component. If no button is pressed, then the name of the device is set based on the Bluetooth address, within the function sl_btmesh_provisionee_on_init(), when it is called to signal the initialization of the Bluetooth mesh node stack.

The callback sl_btmesh_provisionee_on_init() indicates that the Bluetooth mesh node stack initialization is complete. In the background, the sl_btmesh_evt_node_initialized_id is being handled within the Provisionee component. The application first checks the provisioning status. If the node is not provisioned (the default state when the device is first powered up after programming), then the application starts unprovisioned beaconing by calling sl_btmesh_node_start_unprov_beaconing().

The API call sl_btmesh_node_start_unprov_beaconing() takes one parameter (bearer) that selects which bearers are used (PB-ADV, PB-GATT, or both). In this example, both bearers are used. Because the PB-GATT bearer is enabled, the device will begin advertising its provisioning GATT service. This allows the smartphone application to detect unprovisioned nodes.

When unprovisioned beaconing has been started the application waits for the provisioner (in this case, the smartphone app) to start provisioning. Start of provisioning is indicated with the event sl_btmesh_evt_node_provisioning_started_id (see sl_btmesh_provisioning_decorator.c). This is handled in the application code through the sl_btmesh_on_node_provisioning_started()callback.

During provisioning, no actions are required from the user application. The configuration of network keys and other operations are handled automatically by the Bluetooth mesh stack. Both the sensor server and client applications simply start blinking the two LEDs on the WSTK to indicate that provisioning is in progress. Then they wait for the event sl_btmesh_evt_node_provisioned_id (see sl_btmesh_provisioning_decorator.c for more details) that indicates provisioning is complete. This is handled in the application code through the sl_btmesh_on_node_provisioned()callback.

Sensor Thermometer Example#

This section describes basic operation of the Bluetooth Mesh – SoC Sensor Thermometer. It is assumed that the node is already provisioned and publish-subscribe settings have been configured by the smartphone app.

The sensor server may support multiple types of sensors present on the development board, such as a People Count sensor, or the Present Ambient Temperature sensor. The People Count sensor can be simulated by the buttons on the starter kit: PB0 decreases the count and PB1 increases the count, or via cli implementation. The count is maintained in a 16-bit unsigned integer. The Present Ambient Temperature sensor is a Silicon Labs Si7021. Temperature is reported in units of 0.5 degrees Celsius as a signed 8-bit integer.

Upon receiving the sl_btmesh_evt_node_initialized_id event and call to the corresponding callback sl_btmesh_handle_sensor_server_events(), the sensor server node initializes the sensors by calling sl_btmesh_sensor_server_node_init(). This occurs in the btmesh_sensor_server component (see sl_btmesh_sensor_server.c). This function sets the people count to 0 and initializes the temperature sensor hardware. Otherwise, the node starts unprovisioned beaconing and waits for a provisioner. Once provisioned and initialized, the sensor server node simply waits for messages from the client. Events generated by messages from the client are handled in the sl_btmesh_sensor_server.c.

Please note that sensor settings and cadence are not supported at this time so the message handlers are stubs.

  • Get requests are handled by handle_sensor_server_get_request(). The property_id is queried. If the value is non-zero and is a supported value then the sensor data for that property is returned. If the property_id is zero, then all supported sensor data is returned. If the value is non-zero and is an unsupported value, the data length is set to zero to indicate an unsupported property. In all cases, sl_btmesh_sensor_server_send_status() is called to send the status to the client.

  • Get Series requests are handled by handle_sensor_server_get_series_request(). Neither sensor properties supported in this example include either Series State so only the property_id is sent back to the client .

  • Get Column requests are handled by handle_sensor_server_get_column_request(). Neither of the sensor properties include Column State so the same data is sent back to the client, per the specification.

  • Publishing sensor data is handled by handle_sensor_server_publish_event() when the publish period expires. Data from both sensors is published.

  • The Cadence and Settings States for the properties in this example are not included so their handlers simple return the property ID, per the specification.

Sensor Client Example#

This section describes basic operation of the Bluetooth Mesh – SoC Sensor Client. It is assumed that the node is already provisioned and publish-subscribe settings have been configured by the smartphone app. The main purpose of the sensor client is to request sensor data from the sensor server. The sensor client supports two types of sensors: a people counting sensor and a temperature sensor.

Upon receiving thesl_btmesh_evt_mesh_node_initialized_id event, the sensor client node performs the following actions:

  • Initializes the sensor client model by calling sl_btmesh_sensor_client_init().

  • Handles the buttons on the device through calling app_button_press_cb().

  • Requests a sensor descriptor by calling sl_btmesh_sensor_client_get_descriptor() with address 0x0000 to publish the message using the publish parameters set by the configuration client.

  • Starts a timer to periodically request sensor data.

The device buttons are used as follows:

  • PB0 to select the sensor property_id to interact with.

  • PB1 to reset the list of registered devices.

When PB0 is pressed, sensor_client_change_current_property() is called to handle the change. This function increments the variable current_property, which is used to index the properties array containing a list of the supported properties.

When PB1 is pressed update_registered_devices() is called to find and register the devices that support the currently selected property. This is done by calling sl_btmesh_sensor_client_get_descriptor() with the selected property as a parameter. A recurring timer is started with a 2000 ms interval. This timer is used to request the sensor data by calling sl_btmesh_sensor_client_get_sensor_data().

When a message is received from a sensor server, one of the sensor events are triggered. These events are as follows:

Event

Description

Behavior

sl_btmesh_evt_sensor_client_descriptor_status_id

Indicates that a descriptor status message has been received.

Adds the server to the list of registered devices if it was not previously registered.

sl_btmesh_evt_sensor_client_status_id

Indicates that a sensor status message has been received.

Verifies that the data came from a registered device, determines which type of sensor the data comes from, then saves and displays it.