Scene Server

The Scene Server model holds a list of scenes, and exposes functionality for storing and recalling the state of these scenes.

The Scene Server model must be instantiated in every node in the network that participates in scenes. A Scene Server model instance stores the scene data for every model on its own element, and every subsequent element until the next Scene Server.

The Scene Server model adds two model instances in the composition data:

  • Scene Server

  • Scene Setup Server

The two model instances share the states of the Scene Server, but accept different messages. This allows for a fine-grained control of the access rights for the Scene Server states, as the two model instances can be bound to different application keys.

  • Scene Server provides functionality for listing and recalling stored scenes.

  • Scene Setup Server provides functionality for storing and deleting scenes.

The Scene Setup Server model extends the Scene Server model and the Generic Default Transition Time Server model. The Generic Default Transition Time Server model shall be present on the same element as the Scene Setup Server model, or on an element with a lower address.

Operation

The Scene Server stores all scene data persistently using the Settings subsystem. Every scene is stored as a serialized concatenation of each registered model’s state, and only exists in RAM during storing and loading.

It’s up to the individual model implementation to correctly serialize and deserialize its state from scene data when prompted.

Models with scene data

The following models will automatically register scene entries:

Adding scene data for a model

Every model that needs to store its state in scenes must register a bt_mesh_scene_entry structure containing callbacks for storing and recalling the scene data. The scene entry must be declared using BT_MESH_SCENE_ENTRY_SIG for SIG defined models (for example, from the model specification), or BT_MESH_SCENE_ENTRY_VND for vendor-specific models. These macros will allocate the structure in flash, and make them known to the Scene Server model.

For instance, the Generic OnOff Server model defines its scene entry by declaring a bt_mesh_scene_entry structure with the Generic OnOff Server model ID and a set of callbacks:

static ssize_t scene_store(struct bt_mesh_model *model, uint8_t data[])
{
	struct bt_mesh_onoff_srv *srv = model->user_data;
	struct bt_mesh_onoff_status status = { 0 };

	/* Only store the next stable on_off state: */
	srv->handlers->get(srv, NULL, &status);
	data[0] = status.remaining_time ? status.target_on_off :
					  status.present_on_off;

	return 1;
}

static void scene_recall(struct bt_mesh_model *model, const uint8_t data[],
			 size_t len, struct bt_mesh_model_transition *transition)
{
	struct bt_mesh_onoff_srv *srv = model->user_data;
	struct bt_mesh_onoff_status status = { 0 };
	struct bt_mesh_onoff_set set = {
		.on_off = data[0],
		.transition = transition,
	};

	srv->handlers->set(srv, NULL, &set, &status);
}

static void scene_recall_complete(struct bt_mesh_model *model)
{
	struct bt_mesh_onoff_srv *srv = model->user_data;
	struct bt_mesh_onoff_status status = { 0 };

	srv->handlers->get(srv, NULL, &status);

	(void)bt_mesh_onoff_srv_pub(srv, NULL, &status);
}

BT_MESH_SCENE_ENTRY_SIG(onoff) = {
	.id.sig = BT_MESH_MODEL_ID_GEN_ONOFF_SRV,
	.maxlen = 1,
	.store = scene_store,
	.recall = scene_recall,
	.recall_complete = scene_recall_complete,
};

The Generic OnOff Server model only needs to store its OnOff state in the scene, so it always stores and recalls a single byte, as reflected in the bt_mesh_scene_entry.maxlen member of the bt_mesh_scene_entry.

Storing and recalling scene data

When storing and recalling a scene, the Scene Server will go through each model in the composition data elements it represents, and check if there is a scene entry for this model ID.

The Scene Server will use the callbacks in the scene entry to either store or recall the model’s scene data for each model whose model ID is specified in the scene entry.

If you want to skip a specific model instance, return 0 from the store callback.

If a model is extended by other models, it will neither be stored nor recalled with the scene, even if there is a scene entry for this model ID.

If a scene store operation is requested in the middle of a transition between two states, the model should commit the target state to the scene data.

The recall callback contains a transition time pointer, which should be taken into account when implementing the model behavior.

The recall_complete callback is called to notify that recalling scene data is finished. A model can use this callback when it needs to publish its state, which is a composite state and requires all corresponding models to recall their scene data first.

Invalidating scene data

A scene is valid as long as its state is unchanged. As soon as one of the models in a scene detect a change to the scene data, either because of an incoming message or because of an internal change, the node is no longer in an active scene. When a model detects a change to its own data, it calls bt_mesh_scene_invalidate(), passing a pointer to its own model pointer. This resets the Scene Server’s current scene to BT_MESH_SCENE_NONE. The scene has to be stored again to include the change.

States

Current scene: uint16_t

The currently active scene. As soon as one of the models included in the scene changes its state, the scene is invalidated, and set to BT_MESH_SCENE_NONE.

Scene registry: uint16_t[]

The full list of scenes stored by the Scene Server. The scene registry has a limited number of slots, controlled by CONFIG_BT_MESH_SCENES_MAX.

Extended models

None.

Persistent storage

The Scene Server stores the scene registry persistently.

Each scene in the scene registry is stored as a separate serialized data structure, containing the scene data of all participating models. The serialized data is split into pages of 256 bytes to allow storage of more data than the settings backend can fit in one entry.

The serialized scene data includes 4 bytes of overhead for every stored SIG model, and 6 bytes of overhead for every stored vendor model.

Note

As the Scene Server will store data for every model for every scene, the persistent storage space required for the Scene Server is significant. It’s important to monitor the storage requirements actively during development to ensure the allocated flash pages aren’t worn out too early.

API documentation

Header file: include/bluetooth/mesh/scene_srv.h
Source file: subsys/bluetooth/mesh/scene_srv.c
group bt_mesh_scene_srv

API for the Scene Server model.

Defines

CONFIG_BT_MESH_SCENES_MAX
BT_MESH_SCENE_ENTRY_SIG(_name)

Scene entry type definition for SIG models.

Parameters
  • _name[in] Name of the scene entry type

BT_MESH_SCENE_ENTRY_VND(_name)

Scene entry type definition for vendor models.

Parameters
  • _name[in] Name of the scene entry type

BT_MESH_MODEL_SCENE_SRV(_srv)

Scene Server model composition data entry.

Parameters

Functions

void bt_mesh_scene_invalidate(struct bt_mesh_model *mod)

Notify the Scene Server that a Scene entry has changed.

Whenever some state in the Scene has changed outside of Scene recall procedure, this function must be called to notify the Scene Server that the current Scene is no longer active.

Parameters
  • mod[in] Model that invalidated the scene.

int bt_mesh_scene_srv_set(struct bt_mesh_scene_srv *srv, uint16_t scene, struct bt_mesh_model_transition *transition)

Set the current Scene.

All Scene entries of the given Scene Server will transition to the given Scene according to the transition parameters.

Parameters
  • srv[in] Scene Server model.

  • scene[in] Scene to transition to. Cannot be BT_MESH_SCENE_NONE.

  • transition[in] Transition parameters, or NULL to use the default parameters.

Return values
  • 0 – Successfully transitioned to the given scene.

  • -EINVAL – Invalid scene number or transition parameters.

  • -ENOENT – No such scene.

int bt_mesh_scene_srv_pub(struct bt_mesh_scene_srv *srv, struct bt_mesh_msg_ctx *ctx)

Publish the current Scene status.

Parameters
  • srv[in] Scene Server model.

  • ctx[in] Message context, or NULL to publish with the configured parameters.

Return values
  • -EADDRNOTAVAIL – A message context was not provided and publishing is not configured.

  • -EAGAIN – The device has not been provisioned.

Returns

0 Successfully published the current Scene state.

uint16_t bt_mesh_scene_srv_current_scene_get(const struct bt_mesh_scene_srv *srv)

Get the current scene.

This will return the scene that the scene servers is currently in. If there is no currently active scene this will return BT_MESH_SCENE_NONE.

Parameters
  • srv[in] Scene Server model.

Returns

Return the current scene for the scene server.

uint16_t bt_mesh_scene_srv_target_scene_get(const struct bt_mesh_scene_srv *srv)

Get the target scene.

This will return the scene that the scene servers is transiting into. If there is no transition running this will return BT_MESH_SCENE_NONE.

Parameters
  • srv[in] Scene Server model.

Returns

Return the target scene for the scene server.

struct bt_mesh_scene_srv
#include <scene_srv.h>

Scene Server model instance

Public Members

uint16_t all[0]

All known scenes.

uint16_t count

Number of known scenes.

struct bt_mesh_scene_entry
#include <scene_srv.h>

Scene entry type.

Public Members

uint16_t sig

SIG model ID

struct bt_mesh_mod_id_vnd vnd

Vendor model ID

union bt_mesh_scene_entry.[anonymous] id

Model ID

size_t maxlen

Longest scene data

ssize_t (*store)(struct bt_mesh_model *model, uint8_t data[])

Store the current state as a scene.

The callback should fill the data with the current scene state and return the number of bytes written. data is guaranteed to fit maxlen number of bytes.

Param model

[in] Model to get the scene data of.

Param data

[out] Scene data buffer to fill. Fits maxlen bytes.

Return

The number of bytes written to data or a negative value on failure.

void (*recall)(struct bt_mesh_model *model, const uint8_t data[], size_t len, struct bt_mesh_model_transition *transition)

Recall a scene based on the given scene data.

When a scene is recalled, the Scene Server calls this callback for every scene entry that has data for the recalled scene. The handler shall start transitioning to the given scene with the given transition parameters. If the transition is non-instantaneious, for example when bt_mesh_model_transition_time returns a nonzero value, the handler shall publish a status message at the end of the transition.

Param model

[in] Model to restore the scene of.

Param data

[in] Scene data to restore.

Param len

[in] Scene data length.

Param transition

[in] Transition parameters.

void (*recall_complete)(struct bt_mesh_model *model)

Recall a scene is completed.

This callback is called for each model that has a scene entry when recalling a scene data is done and bt_mesh_scene_entry::recall callback has been called for all models. The model can use this callback when it needs to publish its state, which is a composite state and requires all corresponding models to recall their scene data first.

Can be NULL.

Param model

[in] Model to restore the scene of.