• ZLL本地局域网通信过程


    Interface_srpcserver

                                                     -----以灯的状态操作位例

    网关与客户端通过Socket API通信,Socket APIsocket_server.c中实现,socket_server.c中不只实现了网关与客户端的通信,还对客户端进行了简单的管理,如建立客户端列表[c1] ,因为可能有多个客户端连接到同时连接到同一个网关。Socket API是在LwIP的基础上实现的,这一底层通信过程,我们不需要知道它具体怎么实现(但是在具体开发环节中还是需要大量修改和添加功能),只需要知道怎么用Socket API通信。下面就假设网关已经接收到了来自客户端clientFd的命令信息存在*pBuf指向的内存,后面我将介绍网关如何处理这个命令消息。首先调用下面的函数

    void RPSC_ProcessIncoming(uint8_t *pBuf, uint32_t clientFd)

    功能:处理客户端发送到网关的命令信息

    参数:pBuf –网关收到的命令信息

    {

      rpcsProcessMsg_t func;

        func = rpcsProcessIncoming[(pBuf[SRPC_FUNC_ID] & ~(0x80))];

      if (func)

      {

        (*func)(pBuf, clientFd);

      }

      else

      {

        printf("Error: no processing function for CMD 0x%x ", pBuf[SRPC_FUNC_ID]);

      }

    }

    解释:在interface_srpcserver.c的宏定义中定义了这样一个指针函数类型:

    typedef uint8_t (*rpcsProcessMsg_t)(uint8_t *pBuf, uint32_t clientFd);

    上述定义如果难懂可参考http://zhidao.baidu.com/question/170422609.html[c2] 

    第一行定义了一个这样的函数指针

    第二行pBuf[SRPC_FUNC_ID] & ~(0x80)。这里的SRPC_FUNC_ID是在interface_srpcserver.h中定义的一个宏定义常数0pBuf[SRPC_FUNC_ID]就是pBuf的第一个字节的值,由SRPC消息格式可知,第一个字节表示CMD ID,即标识网关收到的是哪个命令,如收到的命令为设置灯的状态,则CMD ID为:RPCS_SET_DEV_STATE      0x82(在nterface_srpcserver.h中已定义),0x82& ~(0x80)得到的结果为2,因此func = rpcsProcessIncoming[2],由字符串数组rpcsProcessIncoming[](在interface_srpcserver.c的开始已定义)可知rpcsProcessIncoming[2]即为RPCS_ZLL_setDeviceState,自此我们完成了命令的解析,也就是说我们知道了客户端要求网关来干什么,接下来的if语句 执行 (*func)(pBuf, clientFd);即为上述定义的指针函数,还是以设置灯的状态的命令为例,前面我们已经得到func即为RPCS_ZLL_setDeviceState,因此这里实际上调用的函数为:

    static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd)

    SRPC消息格式

    CMD字节

    命令长度(N

    数据

    1字节

    1字节

    n个字节

     

    接下来顺藤摸瓜,我们看看这个函数,用户通过客户端发送命令想改变灯的状态,这个命令已经被网关接收到了,接下来网关就要通过主机接口[c3] 发送命令给CC2531来控制终端节点,CC2531是不能直接转发处理客户端发送给网关的命令的,因此网关需对命令解析,提取出需要通过串口传递给CC2531的参数,下面这个函数即实现了此功能。在此还是以设置灯的状态命令为例,RPCS_SET_DEV_STATE消息格式如表所示:

    RPCS_SET_DEV_STATE消息格式

    字节

    描述

    1

    命令ID    Command ID

    0X82

    1

    长度    Length

    13

    1

    地址模式  Address Mode

    1 = 组播或2 =单播     1=groupcast OR 2=unicast                     

    2

    网络地址  Network Address

    NwkAddr或组ID      NwkAddr OR Group ID

    6

    保留的   Reserved

    0

    1

    端点     Endpoint

    设备端点或为0xFF       Devices Endpoint OR 0xFF

    2

    保留的   Reserved

    0

    1

    状态    State

    01(开启或关闭)  0 or 1 (on or off)

     

    static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd)

    功能:This function exposes an interface to set a devices on/off attribute.

    打开一个接口来设置灯的开/关属性

    参数:pBuf - incomin messages  网关接收到的命令消息

    static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd)

    {

      uint8_t  endpoint, addrMode;

      uint16_t  dstAddr;

      bool  state;

     

      //increment past SRPC header

      pBuf+=2;

    // SRPC消息格式可知命令的前两个字节标识命令的ID及命令的长度,这两个字节是告诉网关该如何处理这个命令,并不需要转发给主机接口,因此指针+2跳过

      addrMode = (afAddrMode_t)*pBuf++; 

    // RPCS_SET_DEV_STATE消息格式可知第三个字节标识 地址模式  Address Mode

      dstAddr = BUILD_UINT16(pBuf[0], pBuf[1]);

    //网络地址由两个字节构成,BUILD_UINT16是在hal_defs.h中定义的一个函数方法,将两个字节组合成一个16位无符号整数

      pBuf += Z_EXTADDR_LEN;//指针跳过保留字节,Z_EXTADDR_LEN即为保留字节的个数

      endpoint = *pBuf++;  //从命令中提取端点ID

      // index past panId

      pBuf += 2;// 指针跳过两个保留字节

      state = (bool)*pBuf; //从命令中提取 状态

      // Set light state on/off

    参数已经全部从命令中提取出来了,下面就要通过串口发送参数到CC2531,这是通过下面的函数完成的

      zllSocSetState(state, dstAddr, endpoint, addrMode);

     

      return 0;

    }

    zllSocSetState(state, dstAddr, endpoint, addrMode)

    这个函数实现了通过串口发送数据到CC2531的功能,具体实现在zllSocCmd.c中,这个主机[z4] 接口的问题在此不再叙述

    以上网关完成了一个完整的命令处理过程,主要由三个函数完成:

    void RPSC_ProcessIncoming(uint8_t *pBuf, uint32_t clientFd)   解析命令

     

    static uint8_t RPCS_ZLL_setDeviceState(uint8_t *pBuf, uint32_t clientFd)   提取参数

     

    zllSocSetState(state, dstAddr, endpoint, addrMode);    主机接口发送命令

     

    上面我是以“设置灯的状态”命令为例的,这个功能不需要网关返回数据给客户端,如果客户端发送的命令为“获取灯的状态”,则网关还需将灯的状态信息返回给客户端。前面的过程与上例相同,

    void RPSC_ProcessIncoming(uint8_t *pBuf, uint32_t clientFd)   解析命令

    static uint8_t RPCS_ZLL_getDeviceState(uint8_t *pBuf, uint32_t clientFd)  提取参数

    zllSocGetState(dstAddr, endpoint, addrMode);  主机接口发送命令

    假设通过主机接口获得了“灯的状态”存放在变量state中,接下来我们就要将这个状态数据返回给客户端。这是就需要调用函数:

    void RPCS_ZLL_CallBack_getStateRsp(uint8_t state, uint16_t srcAddr, uint8_t endpoint, uint32_t clientFd)

    {

      uint8_t *pSrpcMessage, *pBuf; 

       

      //RpcMessage contains function ID param Data Len and param data

      pSrpcMessage = malloc(2+ 4);

     

      pBuf = pSrpcMessage;    //使两个指针指向同一内存

     

      //Set func ID in RPCS buffer

      *pBuf++ = RPCS_GET_DEV_STATE_RSP;

      //param size

      *pBuf++ = 4;

       

      *pBuf++ = srcAddr & 0xFF;

      *pBuf++ = (srcAddr & 0xFF00) >> 8;

      *pBuf++ = endpoint;

      *pBuf++ = state & 0xFF; 

           

      //Store the device that sent the request, for now send to all clients

      srpcSendAll(pSrpcMessage); 

     

      //printf("RPCS_ZLL_CallBack_addSceneRsp-- ");

                       

      return;             

    }

    上面的函数是按照下面的命令格式来装载数据的,最后调用srpcSendAll(pSrpcMessage);  函数将封装好的信息发送给所有客户端

    RPCS_GET_DEV_STATE_RSP消息格式

    字节

    描述

    1

    命令ID   Command ID

    0X07

    1

    长度    Length

    0x4

    2

    网络地址  Network Address

    0x1234

    1

    端点   End Point

    0X56

    1

    状态     state

    0X0

    srpcSendAll(pSrpcMessage);是通过调用socket_server.c中的

    int32 socketSeverSendAllclients(uint8* buf, uint32 len)来实现的

     

     

     

    参考Linux gateway远程过程调用设计方法,下面面对的问题主要就是:

    一.   LwIP的基础上能不能实现类似Linux gatewaysocket_server

    二.   Interface_srpcserver能不能准确移植到STM32

    三.   主机接口能不能准确移植到STM32[c5] 

    四.   主机接口与interface_srpcserver如何实现数据交互


     [c1]如何做的?不同的客户端如何区分的?

     [c2]这个附注加得好,别人就可以更好的学习相关的内容了,以便共同提高。

     [c3]也就是吕慧珍和谢红涛正在做移植的部分。

     [z4]红色字体表示的为Interface_srpcserver主机接口交互部分

     [c5]这部分吕慧珍他们正在做,应该问题不大。





    附件列表

  • 相关阅读:
    手机号码正则表达式
    POJ 3233 Matrix Power Series 矩阵快速幂
    UVA 11468
    UVA 1449
    HDU 2896 病毒侵袭 AC自动机
    HDU 3065 病毒侵袭持续中 AC自动机
    HDU 2222 Keywords Search AC自动机
    POJ 3461 Oulipo KMP模板题
    POJ 1226 Substrings KMP
    UVA 1455 Kingdom 线段树+并查集
  • 原文地址:https://www.cnblogs.com/star91/p/4888968.html
Copyright © 2020-2023  润新知