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.

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 as scene entries:

All models that extend these models will automatically become part of the scenes as well.

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 registered with a valid bt_mesh_scene_entry_type structure, which defines the store and recall behavior of the scene entry.

For instance, the Generic OnOff Server model defines its scene entry by adding a bt_mesh_scene_entry structure to every bt_mesh_onoff_srv, and registering it with a common type:

static ssize_t scene_store(struct bt_mesh_model *mod, uint8_t data[])
{
	struct bt_mesh_onoff_srv *srv = mod->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 *mod, const uint8_t data[],
		       size_t len, struct bt_mesh_model_transition *transition)
{
	struct bt_mesh_onoff_srv *srv = mod->user_data;
	struct bt_mesh_onoff_status dummy;
	struct bt_mesh_onoff_set set = {
		.on_off = data[0],
		.transition = transition,
	};

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

static const struct bt_mesh_scene_entry_type scene_type = {
	.maxlen = 1,
	.store = scene_store,
	.recall = scene_recall,
};

The Generic OnOff Server model only needs to store its OnOff state in the scene, so it always stores and recalls a single byte. The restore call contains a transition time pointer, which should be taken into account when implementing the model behavior.

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.

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 shall call bt_mesh_scene_invalidate(), passing its own scene entry. 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.

Persistent storage

The Scene Server stores the scene registry and the current scene 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_MODEL_SCENE_SRV(_srv)

Scene Server model composition data entry.

Parameters

Functions

void bt_mesh_scene_entry_add(struct bt_mesh_model *mod, struct bt_mesh_scene_entry *entry, const struct bt_mesh_scene_entry_type *type, bool vnd)

Register a scene entry.

This function fills all fields of the supplied bt_mesh_scene_entry structure, and registers it to the correct Scene Server.

Scene Servers store scene data for all models in their own element, and every subsequent element until the next Scene Server. If a Scene Server is found for this entry, the srv parameter will point to it when this function returns. If srv is NULL, this means no Scene Server was found, and Scene data will not be stored for this entry.

Note

This function must be called as part of the model initialization procedure to correctly recover a scene on startup. The initial Scene is recovered as part of the model start procedure.

Parameters
  • [in] mod: Model this scene entry represents.

  • [in] entry: Scene entry.

  • [in] type: Scene entry type.

  • [in] vnd: Whether this is a vendor model.

void bt_mesh_scene_invalidate(struct bt_mesh_scene_entry *entry)

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
  • [in] entry: Scene entry that was invalidated.

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
  • [in] srv: Scene Server model.

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

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

Return Value
  • 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.

Return

0 Successfully published the current Scene state.

Parameters
  • [in] srv: Scene Server model.

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

Return Value
  • -EADDRNOTAVAIL: A message context was not provided and publishing is not configured.

  • -EAGAIN: The device has not been provisioned.

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.

Return

Return the current scene for the scene server.

Parameters
  • [in] srv: Scene Server model.

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.

Return

Return the target scene for the scene server.

Parameters
  • [in] srv: Scene Server model.

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_type
#include <scene_srv.h>

Scene entry type.

Public Members

size_t maxlen

Longest scene data

ssize_t (*store)(struct bt_mesh_model *mod, 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.

Return

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

Parameters
  • mod: Model to get the scene data of.

  • data: Scene data buffer to fill. Fits maxlen bytes.

void (*recall)(struct bt_mesh_model *mod, 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.

Parameters
  • mod: Model to restore the scene of.

  • data: Scene data to restore.

  • len: Scene data length.

  • transition: Transition parameters.

struct bt_mesh_scene_entry
#include <scene_srv.h>

Scene entry.

Every model that stores data in scenes must own a unique scene entry, and register it with a Scene Server through bt_mesh_scene_entry_add.

Parameters in this structure will be filled by bt_mesh_scene_entry_add, and should not be manipulated directly.