前言

继上一篇Vendor Model浅析,大家如今知道,不管是SIG Model还是Vendor Model,其组成的结构都是一样的,即Model ID + Opcode + Message;因此,上篇的文章为本篇章创建红旭Model提供了理论的基础,既然要创建红旭Model,那么我们先看看红旭的开发板又有哪些功能,废话不多说:上图!!!

功能定义

前言可知,红旭的开发板共有4个用户按键、4个LED灯、1个串口、一个USB和NFC接口;然而,此次红旭Model只用到按键、LED以及串口,其具体的功能定义如下:

按键

小编在什么是Element和Model中就讲过,一个节点可以同时存在Server和Client模型,即控制模型(Control Model);因此,按键的具体功能定义如下:

至少,按键1和按键2的功能定义,读者们都很好理解;但是,按键3和按键4则是单包与分包发送的区别,其也将用于下一篇的自主分包与MESH协议分包重组的区别讲解时使用;

LED

对于红旭开发板的4个LED定义为如下几个功能:

串口或者RTT

串口或者RTT主要将对端节点发送过来的Vendor消息 (自定义的数据,如字符串、长数据包等等) 打印出来

参数定义

上述的内容,讲的是开发板相关外设的功能定义;接下来,小编将讲解如何创建红旭模型;如按键中所述,模型分SERVER、CLIENT和CONTROL模型三种:

服务端模型

这是用的相对较多的一种模型,大部分情况下均属于被动的状态,换句话就是说被动响应;小编在前言中就讲解,不管是哪种类型的模型,其组成部分均是由Model ID + Opcode + Message三部分组成;

Model ID

Vendor Model浅析可知:

Vendor Model ID = Company ID + Vendor-Assigned Model ID

为了更好理解上述的内容,小编这里以红旭的服务端模型ID为例:

其中,Company ID为0x0059即Nordic,而小编给红旭定义的Vendor-Assigned Server Model ID为0x0000,因此红旭的服务端模型为0x00590000;

Opcode

简单地来说,有什么类型的操作码就决定了你这个模型有什么样的功能;而此时小编想要创建的红旭模型就是一个能传自定义数据的透传模型,即你一次可以传输最大384字节的数据,也可以传只有一个操作码的数据,任君喜欢;

可能有读者会疑问为什么自定义的操作码还要或上0xC0?,不知道读者们对Vendor Model浅析的内容还有没有印象,即Vendor Model操作码的最高的2个有效位必须是11

虽然,在红旭服务端模型中发送的是上述的两个操作码及其携带的消息,但是其要处理红旭客户端模型发送过来的数据,仍然需要将客户端操作码对应的回调函数映射了,即:

Message

这里也就是很多读者叨叨念的想要传送出去的自定义数据内容,针对 HX_MODEL_SERVER_OPCODE_RXHX_MODEL_SERVER_OPCODE_STATUS两个操作码,其携带消息的处理函数如下:

客户端模型

Model ID

服务端模型所述,小编将红旭的Client Model的模型ID定义为0x00590001;

Opcode

相较于红旭服务端模型一味地被动接收,客户端模型则用于自定义透传数据的主动发送,其相对应的操作码定义如下:

那么,上述的操作码具体的功能是什么呢?

同样的,为了能有效地处理服务端模型应答的消息,客户端模型也是需要对客户端模型的操作码与回调处理函数进行映射的,详情如下所示:

Message

对于客户端模型而言,上述的3个操作码分别对应的处理函数如下:

Opcode

同上述的服务端模型.Opcode客户端模型.Opcode

Message

同上述的服务端模型.Message客户端模型.Message

流程梳理

小编在上述中已经讲解了服务端以及客户端模型的各个组成部分,对于天资聪颖的读者来说,结合前面几篇的内容,我相信这一类读者应该知道如何去创建自己的模型;而对于跟小编一样天资愚钝的读者,则需要更加努力地去看接下来的内容了;上面我们明白了创建一个模型需要什么,但是从无到有是怎么样的一个过程呢?仍然是老规矩:上图!!!

至于模型ID操作码回调函数的内容,上述的服务端模型以及客户端模型已经描述地很清楚了,那么小编这里着重要讲得是初始化自定义模型应用处理函数以及应用层调用并处理自定义的模型

初始化自定义模型

上述的内容已经分别讲解了Model IDOpcodeMessage;那么,又是如何将这三个参数串联起来呢?这里以红旭的服务端模型为例:

由上述的函数可知,将我们之前定义的Model IDOpcode以及其对应的回调函数均覆盖了;最终通过Nordic提供的access_model_add API函数,就将这些内容串联起来了,至于Message的内容则放在应用处理函数中处理;当access_model_add API函数调用之后的返回值为0,那么此时自定义的模型就意味着创建成功;一旦已经添加成功的操作码被接收到,那么MESH协议栈就会将自定义的操作码回调函数上抛到应用层,如HX_MODEL_CLIENT_OPCODE_TX操作码被接收到,那么其对应的hx_model_opcode_tx_cb回调函数就会被触发 为了实现订阅地址的功能,还需要通过access_model_subscription_list_alloc API函数通知MESH协议栈,让其为此模型分配一个订阅列表;

应用处理函数

应用处理函数的意思就是说,当自定义的透传数据已经随实参传入相对应的操作码回调函数,此时应用层处理这些数据的函数,这里小编以HX_MODEL_CLIENT_OPCODE_TX操作码的回调函数hx_model_opcode_tx_cb被触发为例;

其中 p_server->p_callbacks->tx_handler(p_server, p_message->p_data, data_length) 就是应用处理函数,而tx_handler函数则需要用户在应用层自定义,其函数原形如下:

其中形参p_data就是获取得到的自定义透传数据,而形参length则是获取的数据的长度;然而,具体怎么处理这些数据则因人而异

应用层调用并处理自定义的模型

当相对应的操作码的回调函数被触发,应用层又应该如何获取客户端发送过来的数据,以便做进一步地处理;小编这里以HX_MODEL_CLIENT_OPCODE_TX操作码以及其回调函数hx_model_opcode_tx_cb为例;老规距,上图!!!

上图可知:

  1. HX_MODEL_CLIENT_OPCODE_TX操作码的hx_model_opcode_tx_cb回调被触发
  2. 当回调函数被触发;tx_handler则处理HX_MODEL_CLIENT_OPCODE_TX操作码携带的自定义透传数据;
  3. 因为HX_MODEL_CLIENT_OPCODE_TX操作码的消息是带应答,因此当处理完自定认的透传数据之后,还需要应答客户端模型,如HX_MODEL_SERVER_OPCODE_STATUS所示;

功能实现

小编在功能定义中定义了相关的功能,主要就是定义了红旭开发板按键LED,其中LED的功能比较容易,只需要接收相应的消息并点亮或者关闭LED灯即可,主要的功能实现在于按键的处理;这里,小编一一对上述的按键功能进行分解:

这里小编将通过两种方式来实现上述的功能:

  1. 采用Client和Server模型各两个
  2. 采用两个Control模型

Client-Server模型

如果采用这种方式的话,就意味着需要新增服务端模型*2客户端模型*2,但是这个时候必须将两个完全相同的模型放在不同的元素下,如下图所示:

小编在上述篇幅中已经分别讲解了Client和Server模型的操作码、回调函数、应用层处理函数等等,那么如果将这些定义好的模型能增加至元素下呢?如何处理操作码所携带的消息呢?这里小编以新增两个Client模型为例

  1. 根据自己的模型个数,修改相对应的宏ACCESS_MODEL_COUNT

    小编是基于Light Switch工程的基础上新增两个模型,由于该工程已经有3个模型了,因此这里ACCESS_MODEL_COUNT宏设置为5

  2. 根据自己的模型数量以及类型,修改相对应的宏ACCESS_ELEMENT_COUNT

    因为小编新增的是两个类型完全相同的模型,需要将这两个模型放在不同的元素下,所以这里设置为2

  3. 完成上述的2个步骤之后,现在开始定义应用层处理函数

  4. 新添两个Client模型至MESH协议栈

    其中,CLIENT_MODEL_INSTANCE_COUNT宏为2,因为我们需要将两个完全相同的模型添加至不同的元素下;如果返回的状态值为0即说明模型增加成功,否则失败;至于,操作码所映射的回调函数也成功映射了,这就意味着当接收到对应的操作码时,其映射的回调函数就会被协议栈向应用层上抛;最终的效果就同上述描绘的

Control 模型

流程跟上述的Client-Server模型是完全一样的,只不过其不需要占用过多的模型,只需要两个控制端模型即可,而上述的Client-Server模型要实现相同的功能,则需要4个模型;该模型新添至Mesh协议栈的操作如下所示:

其中,CONTROL_MODEL_INSTANCE_COUNT表示我要新增多少个控制模型,并将其附于不同的元素下;这里还有一点需要注意的是:每个模型都要填充应用层的回调处理函数,如:

最终成功添加的效果如下图所示:

更完整的源码请参考《创建红旭Model》文件夹

效果展示

小编这里以控制模型为例,演示一个控制模型同时支持服务和客户端模型的事例:

从上述的实验结果,我们可以看出控制模型已经成功地被添加并正常运行;注意:以上的操作均是在同一个模型下执行的。