一.模型的简介
在蓝牙Mesh解决方案中,模型用于定义节点的功能。每个模型表示一组状态和行为,并定义用于与模型状态交互的消息。模型的一个例子是配置模型,它是所有mesh设备中必须的一个模型。此模型表示节点的配置(以各种状态的形式),并提供消息来设置或查询配置参数(行为)。本指南介绍了如何创建新模型的基础知识,您可以实现自己的特定的模型,该模型将使您的设备能够提供自定义状态和行为,而不是来自于已经定义标准模型
二.模型的创建
要创建一个模型有以下几步:
1、定义处理函数:通过access_opcode_handler_t数组,为传入消息定义处理函数表
2、分配并将模型绑定到元素:使用access_model_add() API来分配、初始化模型,并将模型绑定到给定索引处的元素。这个模型实例由输出参数p_model_handle的句柄值标识。调用访问层API函数时使用此句柄。所有模型都必须绑定到一个元素。元素表示设备中的可寻址单元,如灯具中的一个灯泡。因此,启动配置过程为每个元素分配一个单独的单播地址
注意,一个模型可以被扩展成一个或多个模型。这些模型实例可以绑定到不同的元素,从而使完整的模型跨越多个元素,这些模型称为扩展模型
三.发布和订阅
发布:
模型发送消息是通过发布完成的,每个模型都有一个发布地址。消息的发布可以是周期性的,也可以是一次性的,发布的消息可以发送到单播、组播或虚拟地址。相关发布状态的配置通常由Provisioner通过配置模型来控制。发布对于传感器节点定期报告数据读取非常有用。可以使用access_model_publish() API函数发布消息,该函数将根据模型设置(间隔、目标)发布消息
客户端模型也可以向服务器模型发布消息。然而在许多情况下,应用程序希望控制从客户端模型发布的消息的目的地,而不是依赖于外部Provisioner(在许多情况下,客户端的应用程序还是Provisioner)。为此提供access_model_publish_address_set()函数
订阅:
订阅允许模型侦听来自特定地址的传入消息。这可以用来监听,例如,从传感器节点发布的周期性消息。要模型订阅地址,首先需要使用access_model_subscription_list_alloc() API函数分配订阅列表
注意,在使用客户端模型时,不需要订阅要发送消息的地址
四.一个简单的点灯模型
本描述的示例模型很简单,可以作为创建自定义mesh模型的一个很好的入门示例。mesh应用程序使用客户端-服务器结构来,其中客户端和服务器模型使用发布/订阅机制来彼此通信。因此模型将使用两部分来实现:服务器模型(维护OnOff状态)和客户端模型(用于在服务器上操作OnOff状态)。当此服务器模型从客户端模型接收到GET或(可靠的)SET消息时,它将OnOff状态的当前值作为响应发送。这将使客户端保持关于服务器状态的最新信息。下表显示了该模型支持的操作码
在空中发送的操作码是针对特定于的模型的三个字节。完整的操作码是特定的操作码和公司标识符的组合,我们的模型使用以下标识符:
此表中使用的公司标识符是Nordic分配的蓝牙公司ID。在实际应用程序中,应该使用自己公司分配的ID
服务器模型:
当OnOff服务器接收SET和GET消息时,它调用应用程序提供的回调函数,并通过回调函数参数共享/请求数据。为此,我们需要定义一个模型结构体,其中包含了指向回调函数的指针。将此结构体传递给所有消息处理程序。下面的代码显示了服务器模型所需的结构体(simple_on_off_server_t)
typedef struct __simple_on_off_server simple_on_off_server_t;
typedef bool (*simple_on_off_get_cb_t)(const simple_on_off_server_t * p_self);
typedef bool (*simple_on_off_set_cb_t)(const simple_on_off_server_t * p_self, bool on_off);
struct __simple_on_off_server
{
access_model_handle_t model_handle;
simple_on_off_get_cb_t get_cb;
simple_on_off_set_cb_t set_cb;
};
接下来,我们需要定义操作码并创建必要的操作码处理函数来处理服务器模型的传入消息。所有模型的所有操作码处理函数都应使用下面定义的相同函数原型
typedef void (*access_opcode_handler_cb_t)(access_model_handle_